300a4c9ca9
- send_balance_to_budget.py: 본인+가희 계좌 소유자별(by_owner) 집계, schema v1→v2 - inbox_handler.py: OWNER_ASSET 맵으로 소유자별 reconcile(self→증권(효원)/gahee→증권(가희)), asset_name 기반 출력, v2 payload 검증 추가(v1 하위호환 유지) - monthly_settlement.py: 텔레그램 reconcile 라인 소유자별 라벨 - INBOX_TOPICS.md / CLAUDE.md: v2 스키마 문서화 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
8.0 KiB
8.0 KiB
INBOX_TOPICS.md — 에이전트 inbox 메시지 topic 등록부
OpenClaw 에이전트 간 파일 기반 통신의 topic 카탈로그. envelope 형식과 운영 원칙은 CLAUDE.md의 "Agent Inbox Convention" 섹션 참조.
새 topic 추가 시 이 파일에 반드시 등록. 미등록 topic 메시지는 수신자가 failed/로 보낸다.
등록된 Topic
securities_balance
- 방향:
stock→budget - 목적: 본인+가희 증권 계좌별 잔액(평가액·예수금·총자산)을 소유자별로 골디에게 전달, 월간 결산 입력으로 사용
- 트리거: macOS launchd
ai.openclaw.stock.send-balance— 매월 1일 04:30 KST. 골디 결산 cron(05:00) 30분 전. (inbox_handler.py의as_of가드는 1·10·20일을 허용 — 과거 운영 호환 안전망) - schema_version: 2 (v1 하위호환 유지 — 수신자
SUPPORTED_SCHEMA={1,2}) - payload 스키마 (v2):
{
"as_of": "2026-07-01",
"owner_scope": "self_and_gahee",
"accounts": [
{
"label": "일반",
"owner": "self",
"account_no": "",
"deposit": 56032,
"eval_amount": 114294705,
"total": 114350737,
"position_count": 7
},
{ "label": "ISA", "owner": "self", ... },
{ "label": "가희_일반", "owner": "gahee", ... },
{ "label": "가희_ISA", "owner": "gahee", ... }
],
"by_owner": {
"self": { "deposit": 146362, "eval_amount": 188964561, "total": 189110923 },
"gahee": { "deposit": 138469, "eval_amount": 22587331, "total": 22725800 }
},
"totals": {
"deposit": 284831,
"eval_amount": 211551892,
"total": 211836723
}
}
- owner_scope: v2는
self_and_gahee— 본인·가희 모두 발행.accounts[].owner는self|gahee(가희_prefix 라벨이 gahee). 소유자 집계는by_owner.totals는 참고용 grand total. (v1은self_only·by_owner없음, 단일 소유자로 처리) - 수신자(골디) 처리 동작:
- 월간결산 cron 진입부에서
inbox_handler.process_inbox()호출 (fetch_balance 이전 — 분개가 후잉 잔액에 반영되어 결산이 분개 후 스냅샷을 보도록) by_owner의 각 소유자 total 과 후잉 자산(self→증권(효원),gahee→증권(가희))의 차액을 소유자별로 reconcile:- 차액 > 0 → 차변
증권(효원|가희)/ 대변주식평가수익자동 분개 (손익 계정은 소유자 공용) - 차액 < 0 → 차변
주식평가손실/ 대변증권(효원|가희)자동 분개 |차액| < 1만원→ 노이즈로 간주, 분개 skip (processed 처리)|차액| > 1억원→ 안전 가드 발동, 분개 거부 + 텔레그램 alert +failed/이동- 후잉에 해당 자산 항목 없으면
skipped(분개 안 함)
- 차액 > 0 → 차변
- 소유자 하나라도 rejected/journal_failed 면
failed/이동·미처리. 재실행 시 이미 분개된 소유자는 fresh 조회로 차액≈0 aligned → 중복분개 없음 (reconcile는 목표값으로 맞추기라 자연 idempotent) - 정상 처리 후
processed/로 이동,state/inbox_state.json의processed[]에 message_id 누적 (idempotency, 최근 1000개) - 결산 메일 본문에
## 인박스reconcile 섹션(소유자별 라인), 텔레그램에 한 줄 요약 추가. 메일 "자산 계정별 변동"은 후잉 자산 전수 순회라증권(가희)도 자동 표시
- 월간결산 cron 진입부에서
- GC / 적체 정책 (월간결산 cron 진입부에서 매월 자동 수행):
processed/의 mtime 30일 초과 envelope 자동 삭제 (gc_processed)failed/적체가 5건 이상이면 결산 메일·텔레그램에 ⚠️ alert 한 줄 추가 — 사람이 검토 후 수동 삭제 (자동 삭제 안 함, CLAUDE.md 원칙 준수)
- 실패 조건 (→
failed/+ 텔레그램 자가 알림):- JSON 파싱 실패
- envelope 키 누락 /
to != budget/ 미등록 topic / 미지원schema_version - payload 키 누락 (
as_of,accounts,totals,owner_scope) as_of가 매월 1·10·20일이 아님totals/by_owner.*의{deposit,eval_amount,total}음수 또는 100억 초과accounts[].total합계가totals.total과 불일치by_owner에 미등록 소유자 (self/gahee 외) 또는 구조 오류- 차액이 1억원 초과 (분개 거부)
- 후잉 webhook 분개 실패
- 관련 스크립트:
- 송신:
agents/stock/workspace/scripts/send_balance_to_budget.py - 수신:
agents/budget/workspace/skills/monthly-settlement/scripts/inbox_handler.py(단독 실행 가능,--dry-run지원) - 통합:
agents/budget/workspace/skills/monthly-settlement/scripts/monthly_settlement.py진입부에서 호출
- 송신:
improvement_review
- 방향:
main|stock|budget→cody - 목적: 에이전트가 자기 워크스페이스를 자체 개선한 뒤 코디에게 검증·후속 개선을 위임. 코디 세션이 떠 있을 때 incoming을 비동기로 처리.
- 트리거: 에이전트가 자체 판단으로 스크립트·스킬·문서·설정을 수정한 직후 (cron/launchd 자동 발화 X — 작성 주체는 항상 에이전트 자신)
- schema_version: 1
- payload 스키마:
{
"change_type": "script_update | new_skill | config_update | doc_update | scheduled_job | other",
"changed_paths": ["agents/stock/workspace/scripts/foo.py"],
"summary": "한 줄 변경 요약",
"rationale": "왜 변경했는지 (자연어 OK — 지시문 아닌 맥락 설명)",
"self_review_notes": "본인 self-check 결과 (테스트·엣지케이스·미해결)",
"test_evidence": {
"command": "python3 -m ...",
"exit_code": 0,
"output_excerpt": "..."
},
"concerns": [
{ "area": "tz_handling", "question": "naive datetime 잔존 여부" }
],
"priority": "low | normal | high"
}
- 자연어 필드 예외: 이 토픽은 payload에 자연어 필드(
summary,rationale,self_review_notes,concerns[].question)를 허용한다. 코디가 사람-에이전트로서 변경 의도를 읽어야 하기 때문. 단 이는 컨텍스트 설명이지 LLM 행동 지시문이 아니다. "X를 해줘" 류 명령문 금지, 사실·관찰·우려만 기록. - 수신자(코디) 처리 동작:
- 세션 기동 시
agents/cody/inbox/incoming/스캔 → envelope 개수·summary 목록을 관리자님에게 보고 - 관리자님이 우선순위 결정하면 코디가
changed_paths·rationale·concerns기반으로 검증 - 필요 시 코디가 직접 개선 수행 (관리자님 동의 받은 위험 작업은 별도 확인)
- 완료 후 envelope을
processed/로 이동, 같은 basename에_report.md동봉 (검증 결과·후속 개선·잔여 위험) - 스키마 위반(필수 키 누락,
to != cody, 미지원 schema_version)은failed/로 이동 후 관리자님에게 보고
- 세션 기동 시
- 실패 조건: JSON 파싱 실패 / envelope 키 누락 /
to != cody/ 미등록change_type/ 미지원 schema_version /changed_paths빈 배열 또는 워크스페이스 밖 경로 - GC: 코디가 새 envelope을
processed/로 옮기는 그 시점에, 같은 디렉터리의 mtime 7일 초과 항목을trash로 정리한다 (launchd 같은 별도 트리거 없음).failed/는 사람이 검토 후 수동 정리 (자동 삭제 X) - 관련 스크립트: 헬퍼 미정 — 일단 에이전트가 직접 envelope JSON을 작성한다. 패턴이 굳으면 추후
workspace/scripts/cody_review.py류로 추출
등록 템플릿
새 topic 추가 시 복사해서 채우기:
### `<topic_name>`
- **방향:** `<from>` → `<to>`
- **목적:** 한 줄 설명
- **트리거:** 언제 발송되는지 (cron/launchd/이벤트)
- **schema_version:** 1
- **payload 스키마:**
```json
{
"field1": "...",
"field2": "..."
}
```
- **수신자 처리 동작:** payload 받으면 어떤 작업 수행
- **실패 조건:** 어떤 경우 `failed/`로 보내는지
- **관련 스크립트:** 송신측·수신측 코드 위치
변경 이력
- 2026-04-26 — 초기 컨벤션 수립, 빈 등록부 생성