The shared AgentConversationDispatcher permanently retains one KV record for every subject it has ever dispatched. The automation KV API stores all keys for an automation in one document capped at 64 KiB. The live OSS reviewer accumulated 296 records and reached 65,351 bytes, after which every successful conversation dispatch ended with PUT /v1/kv/agent-conversation-* returning HTTP 413.
This affects every extension using the shared dispatcher, including PR review, issue triage, and issue implementation. The conversation ID is deterministic and the conversation itself remains stored by agent-server; the KV entry only records the latest delivery.
The durable fix should keep delivery deduplication while bounding or releasing dispatcher state after work is complete. It should also recover cleanly when upgrading an automation whose existing dispatcher records already fill the KV document.
OpenHands AI triage
The following comments and acceptance criteria were added by the OpenHands AI agent.
Triage
The shared AgentConversationDispatcher in skills/github/scripts/agent_conversation.py writes one permanent KV record per subject (agent-conversation-<uuid5>) and never removes it, so the per-automation KV document (a single JSON document the automation service caps at 64 KiB) grows without bound. The reporter observed the live OSS reviewer accumulate 296 records / 65,351 bytes, after which every dispatch's PUT /v1/kv/agent-conversation-* returned HTTP 413. This blocks all three consumers of the shared dispatcher: github-pr-reviewer, github-issue-triage, and github-issue-to-pr.
The fix belongs in the shared dispatcher so all three consumers recover at once. Deterministic conversation IDs and dedup-on-delivery must be preserved: a re-delivery must resume the same agent-server conversation rather than restart work, and the conversation itself is not the dispatcher's to own. The smallest coherent scope is the dispatcher's own state handling plus its tests.
Non-goals: changing which subjects are dispatched or how triggers are evaluated; changing the automation service's 64 KiB cap or adding a hosted migration; changing the conversation-persistence model in agent-server; documenting new configuration surface that the fix does not add.
Acceptance Criteria
The shared
AgentConversationDispatcherpermanently retains one KV record for every subject it has ever dispatched. The automation KV API stores all keys for an automation in one document capped at 64 KiB. The live OSS reviewer accumulated 296 records and reached 65,351 bytes, after which every successful conversation dispatch ended withPUT /v1/kv/agent-conversation-*returning HTTP 413.This affects every extension using the shared dispatcher, including PR review, issue triage, and issue implementation. The conversation ID is deterministic and the conversation itself remains stored by agent-server; the KV entry only records the latest delivery.
The durable fix should keep delivery deduplication while bounding or releasing dispatcher state after work is complete. It should also recover cleanly when upgrading an automation whose existing dispatcher records already fill the KV document.
OpenHands AI triage
The following comments and acceptance criteria were added by the OpenHands AI agent.
Triage
The shared
AgentConversationDispatcherinskills/github/scripts/agent_conversation.pywrites one permanent KV record per subject (agent-conversation-<uuid5>) and never removes it, so the per-automation KV document (a single JSON document the automation service caps at 64 KiB) grows without bound. The reporter observed the live OSS reviewer accumulate 296 records / 65,351 bytes, after which every dispatch'sPUT /v1/kv/agent-conversation-*returned HTTP 413. This blocks all three consumers of the shared dispatcher:github-pr-reviewer,github-issue-triage, andgithub-issue-to-pr.The fix belongs in the shared dispatcher so all three consumers recover at once. Deterministic conversation IDs and dedup-on-
deliverymust be preserved: a re-delivery must resume the same agent-server conversation rather than restart work, and the conversation itself is not the dispatcher's to own. The smallest coherent scope is the dispatcher's own state handling plus its tests.Non-goals: changing which subjects are dispatched or how triggers are evaluated; changing the automation service's 64 KiB cap or adding a hosted migration; changing the conversation-persistence model in agent-server; documenting new configuration surface that the fix does not add.
Acceptance Criteria
agent-conversation-*records it owns, so retained dispatcher records stop growing by one per subject indefinitely.(subject, delivery)for a completed conversation still reportsdeduplicated(orin_progresswhile running) and does not start a second conversation, while a newdeliveryfor a known subject still resumes the same deterministic conversation ID.PUT /v1/kv/agent-conversation-*succeeds instead of failing with HTTP 413.tests/test_agent_conversation_dispatch.py(and/ortests/test_github_reviewer_delivery.py), and the existing dispatcher tests still pass viauv sync --group testthenuv run pytest -q.skills/github-pr-reviewer/scripts/worker.py,skills/github-issue-triage/scripts/worker.py,skills/github-issue-to-pr/scripts/worker.py) continue to dispatch through the shared dispatcher with no per-consumer duplication of the state-bounding logic, and their tests pass.