Skip to content

feat(agent-runtime): draft rationale from the audit pass + on-demand drafting - #866

Open
kmonsoe wants to merge 1 commit into
feat/conv-review-queue-read-modelfrom
feat/agent-runtime-draft-rationale
Open

feat(agent-runtime): draft rationale from the audit pass + on-demand drafting#866
kmonsoe wants to merge 1 commit into
feat/conv-review-queue-read-modelfrom
feat/agent-runtime-draft-rationale

Conversation

@kmonsoe

@kmonsoe kmonsoe commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Stacked on #865 (base is feat/conv-review-queue-read-model — retarget to main before merging if #865 lands first, per the usual stack discipline).

Implements handover item 4 ("reasoning is nearly free") plus the runtime half of "Ask for a draft":

  • rationale in the audit contract (agent-runtime/src/audit.ts): the audit pass now returns {"rationale": "...", "actions": [...]} — one or two sentences for the human reviewer stating what the reply asserts and what grounds it. Parsed defensively (trimmed, capped at 1000 chars, null when absent); all fail-open paths return rationale: null.
  • Parked on the draft: in draft mode the handler passes rationale + the turn's toolNames through setDraftReply; backend stores them on the draft_reply metadata (retrievedDocumentIds already lived there). The review pane's "why" block reads straight off the draft and hides when no rationale is present — no auditEnabled plumbing needed (it has none in production today).
  • draft-request handler mode: the runner subscribes to conversation.draft_requested (emitted by POST /v1/conversations/:id/request-draft from feat(conv): review-queue read model, internal notes, draft reject stamps #865) and runs the handler with draft delivery forced — even on agentMode: auto conversations — tolerating the requester's own claim and an existing assignee. Voice/closed/no-end-user/off guards stay.
  • Event plumbed through realtime-event-bus (in-process bus) and the agent-runtime realtime client, wired in agent-host/src/runner.service.ts next to greet.

Tests

  • agent-runtime: 466 passed (new: rationale surfaced/capped/nulled, rationale lands in setDraftReply opts, requestDraft parks a draft on a claimed auto conversation without posting).
  • backend-core conv + realtime: 88 passed (new: metadata round-trip of rationale + toolNames). agent-host: 146 passed. Typecheck clean across all three.

🤖 Generated with Claude Code

https://claude.ai/code/session_01CPwvC1MqF1uhpNqC8BmvQN

…drafting

The audit JSON contract gains a reviewer-facing rationale field; the
handler parks it and the turn's tool names on draft_reply metadata via
setDraftReply (REST + in-process clients extended). New draft-request
handler mode answers conversation.draft_requested: forces draft
delivery on auto conversations and tolerates the requester's claim,
completing the Ask-for-a-draft round trip.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CPwvC1MqF1uhpNqC8BmvQN
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant