Reference: GEODE는 v0.89.0에서 외부 SaaS tracing 의존을 제거하고 4개의 자체 관측 렌즈로 전환했습니다. 각 렌즈는 다른 시간 단위와 grain을 가지며, 서로 보완합니다. 한 호출의 lifecycle 전체가 4 렌즈에 모두 기록되도록 설계.
4-Lens 구조
| 렌즈 | 관측 단위 | grain | 위치 | 도입 |
|---|---|---|---|---|
| Hooks | 이벤트 | micro (μs to ms) | core/hooks/system.py | core |
| RunLog | run (LLM 호출 1회) | medium (s) | ~/.geode/runlog/ JSONL | core |
| Audit diagnostics | call (input/output/cost) | per-call (assertion-grade) | core.audit.diagnostics | v0.92.0 |
| Petri Audit | scenario (seeds × turns 격자) | session (min to hour) | Petri × GEODE | v0.92.0+ |
렌즈 1. Hook 시스템
가장 빠른 grain. 모든 lifecycle 이벤트가 발화되고, 카테고리로 그룹화됩니다. listener는 trigger (fire-and-forget) / trigger_with_result (결과 수집) / trigger_interceptor (intercept 가능) 셋 중 하나로 등록.
| 카테고리 | 대표 이벤트 |
|---|---|
| pipeline | PIPELINE_START, PIPELINE_END, PIPELINE_ERROR |
| node | NODE_ENTER, NODE_EXIT, NODE_ERROR, NODE_RETRY |
| analysis | ANALYST_START, ANALYST_COMPLETE, ANALYST_FAILED |
| verification | VERIFICATION_PASS, VERIFICATION_FAIL |
| automation | DRIFT_DETECTED, MODEL_PROMOTED, OUTCOME_COLLECTED, EXPERT_VOTE_CAST, FEEDBACK_PHASE_CHANGED |
| memory | MEMORY_SAVED, RULE_CREATED, RULE_UPDATED, RULE_DELETED |
| tool | TOOL_EXEC_START/END/FAILED, TOOL_RECOVERY_START/END, TOOL_APPROVAL_REQUEST/GRANTED/DENIED |
| session | SESSION_START, SESSION_END |
| model | MODEL_SWITCHED |
| llm | LLM_CALL_START, LLM_CALL_END, LLM_CALL_FAILED, LLM_CALL_RETRY |
| approval | APPROVAL_REQUEST, APPROVAL_GRANTED |
| context | CONTEXT_OVERFLOW, CONTEXT_RESET |
| prompt | PROMPT_ASSEMBLED |
| (reserved) | plugin-specific, 도메인 어댑터가 추가 |
자세히: Hook System.
렌즈 2. RunLog
한 LLM 호출 (run) 단위로 input/output/tool call/reasoning을 시계열로 보관합니다. JSONL 한 파일이 한 run.
# 위치
~/.geode/runlog/<YYYY-MM-DD>/<run-id>.jsonl
# 한 줄 record
{"ts": "...", "kind": "llm_call_start", "model": "claude-opus-4-7", "input_tokens": 1284, ...}
{"ts": "...", "kind": "tool_exec_start", "name": "search_subjects", ...}
{"ts": "...", "kind": "tool_exec_end", "name": "search_subjects", "duration_ms": 312, ...}
{"ts": "...", "kind": "llm_call_end", "output_tokens": 482, "cache_read_tokens": 28000, ...}
{"ts": "...", "kind": "run_end", "total_cost_usd": 0.0127, ...}inspect view ~/.geode/runlog/...로 transcript viewer에서 재생 가능.kind 종류는 hook 이벤트와 1대1 대응.
렌즈 3. Audit Diagnostics (v0.92.0+)
Petri audit가 require하는 per-call assertion 데이터. cache_read/cache_write 메타 + input/output hash + provider response 원본 + cost decomposition. 한 호출의 모든 결정 가능 데이터를 재현 가능한 형태로 저장.
# core/audit/diagnostics.py
@dataclass
class CallDiagnostic:
run_id: str
call_seq: int # run 안에서 N번째 호출
provider: str # anthropic / openai / glm / codex
model: str # claude-opus-4-7 등
input_hash: str # SHA-256[:12] of input
output_hash: str
input_tokens: int
output_tokens: int
cache_read_tokens: int # 캐시 hit
cache_write_tokens: int # 캐시 write
reasoning_tokens: int | None # extended thinking
cost_usd: float
cost_breakdown: dict # {input, output, cache_read, cache_write, reasoning}
latency_ms: int
audit_mode: bool # Petri audit 여부v0.92.0 도입. v0.93+ Petri audit-mode가 이 데이터를 1차 사료로 활용해 시나리오의 재현성을 보장합니다.
렌즈 4. Petri Audit
세션 단위 grain. seeds × turns 격자로 misalignment risk를 측정. Auditor(적대) · Target(GEODE) · Judge 3-role 구성.
- 전체 통합: Petri × GEODE Integration
- 시나리오: Petri Scenarios (Petri 기본 + GEODE 전용)
- 실행: Petri Run
- 차원: Judge 차원
Usage Ledger (v0.66+)
비용 추적 전용 append-only ledger. ~/.geode/usage/<date>.jsonl에 LLM 호출 단위로 token 분해와 cost가 기록됩니다. v0.90.0에서 token tracker dual-record 버그를 수정해 codex/glm의 50-64% duplicate 카운팅이 해소되었습니다.
$ geode history --last 24h $ jq '.cost_usd | add' ~/.geode/usage/2026-05-12.jsonl # 합계 $ jq -c 'select(.cache_read_tokens > 0)' ~/.geode/usage/2026-05-12.jsonl # 캐시 hit만
어떤 렌즈를 언제 쓰나
| 질문 | 1차 렌즈 | 보조 |
|---|---|---|
| 왜 이 도구가 호출됐지? | RunLog (run 단위 trace) | Hook TOOL_EXEC_* |
| 비용이 어디로 갔지? | Usage ledger | Hook LLM_CALL_END 집계 |
| 이 호출이 캐시를 어떻게 썼지? | Audit diagnostics (cache_read/write) | RunLog |
| 같은 입력이 재현되나? | Audit diagnostics (input_hash) | RunLog 비교 |
| 이 에이전트가 안전한가? | Petri audit (시나리오) | Hook VERIFICATION_FAIL |
| 긴 세션에서 어디서 막혔지? | Hook CONTEXT_OVERFLOW | RunLog timeline |
외부 어댑터
자체 stack이 1차지만, 외부 dashboard로 export 필요시 두 가지 경로가 있습니다.
- OpenTelemetry. Hook listener를 OTel exporter로 wrapping해 Tempo/Jaeger/Grafana로 흘림.
- inspect viewer. RunLog JSONL을 그대로 inspect 명령에 입력해 transcript UI로 본다 (Petri 결과와 동일 viewer).
왜 자체 스택인가
- 외부 SaaS lock-in 제거.
- 관측 데이터를 GEODE 내부에서 직접 소유 (RunLog).
- 외부 tracing SDK의 import-time cost가 cold-start lazy loading arc (v0.85-89)와 충돌.
v0.89.0에서 외부 tracing 의존성 + 별도 tracing 모듈을 제거했습니다. 이 페이지 4 렌즈가 정식 관측 경로입니다.