마지막 업데이트 2026-09-18
한 줄 요약. 저장소 ~/git-projects/agent-trace (GitHub Dobraindev/agent-trace). 세 도구가 로컬에 남기는 기록(~/.claude/projects, ~/.codex/sessions, ~/.hermes/state.db)을 읽기 전용으로 파싱해 세션 → 턴 → LLM 호출 / 툴 호출 모델로 SQLite에 저장하고, OTLP span으로 로컬 Phoenix(http://localhost:6006)에 보낸다. 외부 전송은 없다.
판정 원칙. 판정은 룰, LLM은 해석만. 룰이 표시한 턴(또는 사람이 Phoenix에서 표시한 턴)에만 judge가 호출된다. 개선안은 사람이 --yes로 승인해야 파일에 들어간다.
이전 설계와의 차이. 관측성·Judge 설계 문서는 langsmith-cli 사용을 검토했으나 개인정보(아동 실명) 클라우드 전송이 P0 게이트였다. agent-trace는 수집·저장·시각화를 전부 로컬에 두어 그 게이트를 우회했고, LLM에 보내는 것은 judge 프롬프트(턴 요약)뿐이다.
한 문장으로: 코딩 에이전트가 일한 기록을 모아서, 잘못한 턴을 찾아내고, 그 교훈을 에이전트 지침 파일에 되돌려 넣는 도구다. Claude Code·Codex·Hermes는 매 세션을 로컬에 기록하지만 형식이 서로 다르고 사람이 읽기 어렵고, 무엇보다 "이 세션에서 에이전트가 어디서 헛돌았는가"를 알려주지 않는다. agent-trace는 그 빈틈을 채우며, 역할은 네 겹으로 나뉜다.
| 역할 | 하는 일 | 대응 명령 |
|---|---|---|
| ① 통역자 | 세 도구의 서로 다른 기록 형식을 하나의 모델(세션 → 턴 → LLM 호출 / 툴 호출)로 번역한다. Claude Code 턴과 Codex 턴을 같은 기준으로 비교할 수 있게 된다. | 파서 (parsers/) |
| ② 기록 보관소 | 번역한 결과를 SQLite에 쌓고, 화면용으로 Phoenix에 복사본을 보낸다. 과거 세션까지 전부 백필하므로 "3주 전 그 작업 때 에이전트가 왜 20분을 썼는지"를 나중에 찾아볼 수 있다. | backfill watch turns show |
| ③ 감사관 | 룰 7종으로 의심 턴을 표시하고, 표시된 턴만 LLM judge에게 넘겨 방향 이탈·툴 오용·정상 등으로 분류하고 개선 제안을 받는다. 판정은 룰이 먼저, LLM은 해석만 맡겨 비용을 통제한다. | flag judge sync-marks |
| ④ 교정 루프 | 반복되는 제안을 묶어 사람이 승인하면 해당 프로젝트의 CLAUDE.md / AGENTS.md에 규칙 한 줄을 추가한다. 다음 세션의 에이전트가 그 규칙을 읽고 같은 실수를 덜 하게 된다. 이 단계가 도구의 존재 이유이고 앞의 세 겹은 이를 위한 준비다. | propose apply resume |
하지 않는 것. 에이전트 실행에 개입하지 않고, 원본 기록을 수정하지 않으며, 데이터를 외부로 보내지 않는다(LLM judge 프롬프트만 예외). 순전히 사후에 기록을 읽고 판정해 사람에게 제안하는 관찰자다.
비유. 에이전트가 운전자라면 agent-trace는 블랙박스 영상을 모아 위험 운전 구간을 자동으로 찍어주고, 반복되는 실수를 운전 교본에 한 줄씩 추가하는 안전관리자다. Phoenix는 그 영상을 재생하는 모니터이고(사용법), 라이브러리로 내장한 것이 아니라 별도 Docker 컨테이너로 띄운 뷰어다.
rule:* 주석judge 주석서브에이전트(Claude Agent 툴, Codex 서브스레드, Hermes 하위 세션)는 부모 턴 trace 안의 자식 AGENT span으로 중첩되어 한 화면에서 부모·자식 흐름을 함께 볼 수 있다.
cd ~/git-projects/agent-trace
docker compose -f deploy/phoenix/docker-compose.yml up -d # Phoenix (127.0.0.1:6006만 바인딩, 데이터 ~/.local/share/agent-trace/phoenix)
uv sync --extra dev
uv run pytest -q # 207 passed 기대 (실데이터 스모크는 AGENT_TRACE_REAL_SMOKE=1 옵트인)
backfill/watch가 프리플라이트에서 즉시 실패한다. 전송 없이 SQLite만 채우려면 --no-export.uv run agent-trace backfill # 기본 --tool all: Claude → Codex → Hermes 순, 재실행 멱등
uv run agent-trace backfill --tool codex --limit 20
uv run agent-trace watch # Claude·Codex 디렉터리 감시 + Hermes 5초 폴링, Ctrl+C 종료
| 옵션 | 의미 |
|---|---|
--tool all|claude|codex|hermes | 수집 대상. claude_code/claude-code 별칭 허용 |
--limit N | Claude: 최근 N개 부모 파일 + 최근 N개 서브에이전트 파일(각각) · Codex: rollout 파일 전체에서 최근 N개 · Hermes: 미적용(워터마크 기준) |
--force | 변경 없는 파일도 재파싱. 파서 수정 뒤 재export할 때 사용 |
--no-export | Phoenix 전송 생략 |
상시 실행은 README의 launchd plist 예시(~/Library/LaunchAgents/com.chulsu.agent-trace.plist)를 등록한다. 등록은 사용자가 직접 결정한다.
화면 구성·span 속성 표·실서버 검증 필터식·주석 활용의 상세는 Phoenix 트레이스 대시보드 사용법 참고.
http://localhost:6006 → 프로젝트 agent-trace → Sessions: Claude(uuid)·Codex(01a0…)·Hermes(2026…) 세션이 함께 보인다.llm …, tool …, subagent … span. 속성은 OpenInference(input.value, output.value, llm.token_count.*, tool.name) + gen_ai.*.rule:slow_turn 같은 CODE 주석과 judge LLM 주석이 붙는다. 사람이 직접 판정할 때는 여기서 주석을 추가한다(5절).uv run agent-trace turns --limit 20 [--tool codex] [--flagged] # 터미널에서 턴 표
uv run agent-trace show <turn-id> # 프롬프트·타임라인(+ms 오프셋)·응답
uv run agent-trace flag --since-days 30 --push # 룰 평가 → flags 저장 → Phoenix CODE 주석
uv run agent-trace turns --flagged --limit 20
| 룰 | 조건 | 비고 |
|---|---|---|
slow_turn | 턴 지연 > max(도구별 최근 30일 p95, 60초). 표본 20건 미만이면 300초 고정 | 툴 실행·사용자 대기 시간을 분리하지 못해 오탐 가능 |
tool_loop | 동일 (툴 이름, 입력) 호출 3회 이상 | |
tool_error_ratio | 툴 3개 이상이고 에러 비율 40% 이상 | |
user_correction | 다음 사용자 프롬프트가 교정 표현으로 시작(아니/다시/하지 마/왜/wrong/again …) | 사람의 개입 = 무료 라벨 |
after_compaction | 컴팩션 직후 첫 턴 | |
aborted | 턴 중단 | Codex·Hermes만 감지, Claude Code는 항상 False |
thinking_heavy | 사고 토큰 > 2,000이고 출력 토큰의 10배 초과 |
2026-09-14 실측(최근 30일 2,753턴): slow_turn 137 · after_compaction 46 · user_correction 22 · aborted 15 · tool_loop 14 · tool_error_ratio 3. 임계값 Claude 436초 · Codex 386초 · Hermes 300초(floor).
uv run agent-trace judge --limit 5 --push # flagged ∪ 사람 표시 턴 중 미판정 5건
uv run agent-trace judge --turn <turn-id> --dry-run # LLM에 보낼 프롬프트만 출력
uv run agent-trace judge --turn <turn-id> --push
category(wrong_direction / slow / loop / ignored_instruction / over_scope / tool_misuse / ok), severity 0~3, rationale, proposal(CLAUDE.md/AGENTS.md에 넣을 규칙 문장), confidence.ANTHROPIC_API_KEY(또는 ANTHROPIC_AUTH_TOKEN)가 있으면 anthropic SDK(claude-opus-5), 없으면 로그인된 Claude Code CLI(claude -p --json-schema --no-session-persistence). CLI 백엔드는 턴당 약 30초, 판정용 세션은 트랜스크립트로 남지 않는다.verdicts 테이블, Phoenix LLM 주석(judge, label=category, score=severity), reports/YYYY-MM-DD.md.error로 기록되며 다음 실행에서 재시도된다.AGENT_TRACE_JUDGE_REDACT=1로 토큰(sk-, AKIA, ghp_)과 이메일을 마스킹하고, 턴당 입력은 AGENT_TRACE_JUDGE_MAX_CHARS(기본 20,000자)로 제한된다.… turn N)을 열고 Annotations에 주석을 추가한다(annotator HUMAN, 이름 예: manual_check, label bad).uv run agent-trace sync-marks — HUMAN 주석만 human_marks로 회수해 턴에 매핑한다.judge는 사람 표시 턴을 기본 대상에 포함한다.uv run agent-trace propose [--since-days 30] [--min-severity 2] # verdict 제안을 (카테고리, 도구, cwd) 별로 집계 → proposals/YYYY-MM-DD.md
uv run agent-trace apply <proposal-id> --target ~/.claude/CLAUDE.md # diff만 출력
uv run agent-trace apply <proposal-id> --target ~/.claude/CLAUDE.md --yes # 실제 반영
uv run agent-trace resume <turn-id> # claude --resume / codex resume / hermes --resume 명령 출력
apply는 대상 파일 끝의 ## agent-trace 개선 규칙 절 안에만 append한다. 기존 내용은 건드리지 않고, 같은 id는 두 번 들어가지 않는다.CLAUDE.md(없으면 ~/.claude/CLAUDE.md), Codex → AGENTS.md, Hermes → ~/.hermes/SOUL.md.resume는 명령을 출력만 한다. 서브에이전트 턴이면 부모 세션 재개 명령을 낸다.환경변수 또는 ~/.config/agent-trace/.env(환경변수가 우선).
| 변수 | 기본값 | 설명 |
|---|---|---|
AGENT_TRACE_OTLP_ENDPOINT | http://127.0.0.1:6006/v1/traces | 로컬 호스트만 허용. Phoenix REST 주소는 여기서 파생 |
AGENT_TRACE_OTLP_HEADERS | (없음) | k=v,k2=v2 — 다른 OTLP 백엔드용 |
AGENT_TRACE_DB_PATH | ~/.local/share/agent-trace/agent-trace.db | SQLite. 스키마 버전은 PRAGMA user_version(현재 6), 열 때 자동 마이그레이션 |
AGENT_TRACE_CLAUDE_PROJECTS_DIR | ~/.claude/projects | |
AGENT_TRACE_CODEX_SESSIONS_DIR | ~/.codex/sessions | |
AGENT_TRACE_HERMES_DB_PATH | ~/.hermes/state.db | 읽기 전용(mode=ro)으로만 연다 |
AGENT_TRACE_HERMES_POLL_SECONDS | 5 | watch 폴링 주기 |
AGENT_TRACE_MAX_VALUE_CHARS | 8000 | span 속성 문자열 절단 |
AGENT_TRACE_JUDGE_BACKEND | auto | auto|sdk|cli |
AGENT_TRACE_JUDGE_MODEL | sdk claude-opus-5 / cli opus | |
AGENT_TRACE_JUDGE_MAX_CHARS | 20000 | judge 프롬프트 상한 |
AGENT_TRACE_JUDGE_REDACT | 0 | 1이면 토큰·이메일 마스킹 |
show로 타임라인을 보는 것이 안전하다.turn_aborted)·Hermes(end_reason)만 감지한다.~/.local/share/agent-trace/phoenix를 지운 뒤 재기동 → backfill --force(약 1분).turns의 parent? 컬럼에 pending으로 표시된다.backfill 직후 unexported가 0이 아닐 수 있다. 진행 중인 턴이 끝나면 다음 실행에서 자동 재export된다.flag --limit이 오래된 턴부터 선택, 주석 1,000건 페이지네이션 없음 등)은 저장소 docs/superpowers/specs/2026-09-14-agent-trace-design.md §12와 docs/superpowers/reviews/에 있다.| 단계 | 내용 | PR |
|---|---|---|
| Plan 1 | Claude Code 파서 · SQLite · OTLP exporter · Phoenix compose · backfill/watch/turns/show | #1 |
| Plan 2 | Codex·Hermes 파서 · 서브에이전트 중첩 trace · --tool all · 마이그레이션 2~5 | #2 |
| Plan 3 | 룰 7종 flag · LLM judge(SDK/CLI) · Phoenix 주석 push/pull · propose/apply/resume | #3 |
설계·플랜·최종 리뷰 문서는 저장소 docs/superpowers/에 있다. 네이티브 OTel(Claude Code 이벤트, Codex [otel])은 채택하지 않았다 — 트랜스크립트가 이미 레코드별 ms 타임스탬프를 가지고 있고, Codex는 사용자 config 수정이 필요했기 때문이다.