Web·iOS·Android 화면을 WCAG 2.2에 맞춰 설계하고 점검합니다. 화면 읽기와 키보드 조작, 레이블, 대비, 조작 대상 크기를 확인합니다.
- 아이콘 버튼에 설명 추가
- 키보드 조작과 모달 초점 점검
- 대비와 조작 대상 크기 확인
고객이나 거래처에 보낼 답장 초안을 사람의 승인과 연결하고 승인된 본문, 수신 대상, 전송 결과를 기록합니다. 오래된 승인 사용과 중복 전송을 방지하도록 설계합니다.
Operator approval contract with internal filing notices for agent-drafted outbound messages, hashed drafts, epoch-keyed decisions, durable delivery claims and receipts, and a pre-draft baseline gate. Use when an agent drafts messages to external counterparties and a human operator must approve, reject, or steer each send before it leaves.
에이전트가 작성한 대외 메시지 초안을 사람의 승인 후 전송하는 절차와 기록 방식을 정합니다. 내용을 식별하는 해시값과 갱신 시점을 승인에 연결해 수정 전 승인이 새 본문에 사용되는 일을 방지합니다. 전송 담당 처리를 하나로 제한하는 장치와 승인자, 수신 대상, 전송 결과를 남기는 원장의 참고 구현도 포함합니다.
고객, 공급업체, 투자자, 파트너에게 보낼 답장을 에이전트가 작성하고 사람이 확인한 뒤 전송할 때 유용합니다. 초안 등록 전 계약이나 고객 관리 기록을 확인해 이미 아는 사실을 상대에게 다시 묻는 일을 줄입니다. 승인 상태 알림은 확인된 내부 수신 대상으로 제한합니다.
참고 구현은 SQLite를 사용하며 전송 서비스를 직접 호출하지 않습니다. 승인자 인증과 데이터베이스 초기화는 별도로 필요합니다. 결과가 불명확한 전송은 자동 재시도하지 않고 확인 후 기록을 대조합니다. 승인마다 한 번의 자동 전송 시도를 보장하며 외부 전달이 정확히 한 번 완료되는 것은 보장하지 않습니다.
이 소개문은 공개된 SKILL.md를 바탕으로 AI(OpenAI Codex)가 작성했습니다. 정확한 사양은 아래 원문을 확인하세요.
AI가 SKILL.md의 내용만을 근거로 4가지 관점에서 판정했습니다. 스타 수나 인기도는 판정에 넣지 않았습니다.
총점은 각 항목을 A=25점, B=15점, C=5점으로 더한 값입니다. 2026년 10월 19일 기준으로 AI(OpenAI Codex)가 판정했습니다. 참고용이므로 설치 전에 원문도 확인해 주세요.
설치하기 전에 에이전트에게 전달되는 지시 내용을 확인할 수 있습니다.
An agent that talks to external counterparties should never send on its own judgment and should keep the operator informed internally. This skill defines the contract: every outbound draft is filed as an obligation, an operator decides on the exact text, and a delivery ledger proves what went out.
| Object | Meaning |
|---|---|
| Obligation | One thing we owe a counterparty. Status moves drafted, then approved or rejected, then sent. Carries direction, counterparty, channel, and an updated_at epoch. |
| Draft | Sidecar row holding the exact draft text, a sha256 of that text, origin coordinates (platform, channel, thread, user), and priority (P0 to P3). One per obligation, replaced on re-file. |
| Decision | An operator's approve or reject, recorded with the operator id, a nonce, and the draft epoch it was made against. |
| Approval snapshot | Immutable text, hash, epoch and destination recorded by the already-authorized decision writer. Missing snapshots cannot grant dispatch. |
| Claim | Durable reservation with a random token and state; at most one active claim per obligation. |
| Delivery | Ledger row proving one send or notice for one (obligation, decision) pair. |
The reference schema is in references/approval-ledger.sql.
updated_at. That advance is the epoch rotation: any
decision keyed to the old epoch can no longer release the new text.
Otherwise insert a new obligation with status drafted.If a verified internal destination is unavailable, retain the filing result in the internal tool result or operator surface. Never fall back to an external or unknown origin. A tool result exposed to outsiders is not an internal surface.
Filing a draft does not authorize an external response. Any policy-permitted clarifying question or neutral response is a separate outbound decision, subject to the existing mention, channel, draft-only, frozen and never constraints in counterparty-channel-discipline. It must not disclose internal approval metadata.
Before any draft is filed, query the current baseline for the counterparty (a temporal ledger, contract store, or CRM):
force_despite_signed_contract lets the filing through
and stamps [BASELINE_OVERRIDE_SIGNED_CONTRACT] into the draft context.[BASELINE_CHECK_UNAVAILABLE]. The panel sees that the guard was off.
Failures never silently disable the gate.[BASELINE FACTS: ...] digest so the draft lands with current truth.The approval panel lists obligations with status drafted and direction
we_owe_them. Approve or reject writes a decision row carrying the draft
epoch (draft_updated_ts) and flips the obligation status in the same
transaction. A decision whose epoch does not match the current updated_at
is stale and must not release anything.
For an already-authorized approve decision, the same transaction inserts an
immutable obligation_approval_snapshots row: decision and obligation IDs,
current draft epoch, exact text and SHA-256, platform/channel/thread, and kind
draft_sent. The decision writer must establish authorization before writing;
the reference never authenticates an operator or manufactures a decision.
Automatic approval policy is not enabled or expanded by the reference.
Legacy decisions without snapshots require explicit reconciliation or a new
approval; never backfill permission from the current mutable draft.
The SQLite reference is references/approval_claims.py. It grants dispatch permission but never calls transport. Use an existing local reference database initialized from the SQL fixture; the module does not apply schema or production migrations. Only a trusted decision writer may populate approval records. All writers must enable foreign keys and recursive triggers and honor the schema guards; administrative database tampering is outside this model.
claim() opens
its own BEGIN IMMEDIATE transaction, validates the current approved epoch,
exact text, computed SHA-256 and full destination against the snapshot, and
inserts a unique claim before returning its token. A conflict stops the worker
before transport. Completed receipts cannot be claimed again.begin_dispatch() revalidates the binding and atomically changes claimed
to dispatching using the token. Only its winning caller receives
the exact draft_text and destination after commit. Never regenerate text, reread a
mutable sidecar for transport, or reuse the payload for another attempt.
A nested caller transaction is refused; permission cannot depend on a later
caller commit. No database transaction remains open across transport.complete(), which atomically records
the delivery coordinate, marks the claim delivered and flips the obligation
to sent. Identical completion is a no-op; conflicting coordinates fail.
The receipt UNIQUE key deduplicates records, not prior external effects.mark_unknown() records uncertainty.
Unknown claims never expire, reopen, auto-retry or allow another decision for
that obligation to bypass them. A trusted caller may use reconcile() with
confirmed successful coordinate and evidence; the module does not verify
that evidence. An absent receipt is not proof of non-delivery.The guarantee is one automatic dispatch attempt per approved decision, not exactly-once external delivery. A crash after begin-dispatch but before transport can leave zero sends and a held claim. Releasing an unknown outcome for a new attempt would require fencing the original executor and verifying provider semantics; this reference deliberately provides no such retry operation.
| Claim state | Allowed next states |
|---|---|
| claimed | dispatching or cancelled before dispatch |
| dispatching | delivered or unknown |
| unknown | delivered through trusted reconciliation only |
| delivered, cancelled | terminal; decision key cannot be reused |
While a claim is active, database guards freeze obligation, draft and decision writes, including replacements. Snapshots and claims cannot be erased. Cancel a claimed operation with its token before re-filing; the stale token then grants nothing. After dispatch begins, hold new edits or revocation for reconciliation. This serializes changes instead of pretending to recall an in-flight operation.
Rejected decisions and legacy rows without draft sidecars/snapshots never enter
this external draft-send path. Report them on the internal operator surface for
manual handling. Internal receipt footers remain internal:
approved by <operator> · receipt <decision_id> · draft sha256 <prefix>.
Never alter already-approved external text to append workflow metadata.
Focused local validation uses temporary databases, separate connections and a
simulated attempt counter, not a provider or real message:
python3 -m unittest discover -s tests/skills -p 'test_approval_delivery_claims.py'.
The tests require Python 3.11+ with SQLite serialization support; the reference
uses only the standard library. The existing desk-pattern contract checks remain
a separate compatibility check.
A draft may carry auto_send_after (epoch seconds). A sweep approves drafts
whose deadline passed with no decision, recording operator auto-ttl, then
delivery proceeds through the normal path. Operator actions always win: a
decision flips status before the sweep sees it, and a re-file rotates the
epoch and moves or clears the deadline. The sweep re-checks status and epoch
inside the write transaction so a race resolves as a no-op. Drafts without a
deadline stay hard-gated forever.
A draft can name the inbound obligation it answers (signal_obligation_id).
This is the only truthful link for latency measurement (inbound signal to
drafted response) and lets the SLA scan treat that inbound item as answered.
Reject the filing if the referenced row does not exist.
file_request(
draft="Thanks, we can hold the slot until Friday. Which start date works?",
counterparty="acme-supplier",
context="reply to delivery window question",
origin_platform="slack", origin_channel="#acme-shared",
origin_thread="1712345678.000100", priority="P1",
signal_obligation_id=412)
-> {obligation_id: 431, draft_sha256: "9f2c...", refiled: false}
The configured, verified internal ops destination sees:
Draft filed for approval (P1, sha 9f2c8a1b). Waiting on operator.
The counterparty-visible origin channel receives no filing notice. If no verified
internal destination is available, the receipt stays in the internal tool result
or operator surface, with no external fallback.
The operator asks for a shorter draft. Filing again for the same
(counterparty, channel) returns refiled: true, the sidecar text and hash
change, and updated_at advances. An approve clicked on the old panel row
carries the old epoch and is ignored.
DeskApprovalError: baseline gate refused this draft: the ledger shows a
signed contract for 'acme-supplier'. Evidence: master agreement executed
2026-08-14. Recommendation: do not ask. Re-file with
force_despite_signed_contract=true if this is genuinely a new thread.
Confirmed for Friday, start date 2026-09-08.
approved by operator-a · receipt 118 · draft sha256 9f2c8a1b2d3e4f50
아직 리뷰가 없습니다. 사용해 본 소감을 남겨 주세요.
로그인 없이 쓸 수 있습니다. 사용 후기, 질문, 작동하지 않은 환경 등을 편하게 남겨 주세요.
아직 댓글이 없습니다. 첫 댓글을 남겨 보세요.
Web·iOS·Android 화면을 WCAG 2.2에 맞춰 설계하고 점검합니다. 화면 읽기와 키보드 조작, 레이블, 대비, 조작 대상 크기를 확인합니다.
인공지능 에이전트의 문제를 지시, 기억, 도구 실행, 화면 표시 등 12개 계층에서 조사합니다. 코드와 로그를 근거로 원인을 정리하고 심각도에 따른 지적 사항과 수정안을 제시합니다.
실제 개발 과제로 여러 코딩 에이전트를 비교합니다. 성공률, 확인 가능한 API 비용, 소요 시간과 반복 실행의 안정성을 측정해 도입 결정과 업데이트 후 평가에 활용합니다.
AI 에이전트의 도구 구성, 입력과 출력 형식, 오류 복구 절차를 설계합니다. 문맥 정보량을 관리하고 완료율, 재시도 횟수, 성공한 작업당 비용으로 개선을 평가합니다.
오류와 실행 환경을 바탕으로 AI 에이전트가 실패하거나 같은 작업을 반복하는 원인을 조사합니다. 작은 복구 작업을 시험하고 결과와 근거를 인계용 보고서로 정리합니다.
AI 에이전트의 반복 실패와 도구 사용을 기록하고 원인을 좁힙니다. 영향이 제한된 복구 작업과 결과 보고를 통해 근거 있는 재시도를 돕습니다.