Skip to content

fix(voice-call): auto-respond to webhook transcripts#100255

Merged
steipete merged 1 commit into
mainfrom
codex/pr-79336-land
Jul 5, 2026
Merged

fix(voice-call): auto-respond to webhook transcripts#100255
steipete merged 1 commit into
mainfrom
codex/pr-79336-land

Conversation

@steipete

@steipete steipete commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Closes #79118
Supersedes #79336 because the contributor fork predates the current main history and cannot be refreshed through GitHub's verified branch-edit path without replaying more than 21,000 unrelated files.

What Problem This Solves

Fixes an issue where callers using carrier webhook transcription could hear the greeting and have their speech transcribed, but OpenClaw would never generate or speak a reply.

Why This Change Was Made

Both media-stream and carrier-webhook transcripts now use one manager-owned final-speech result and one auto-response handoff. Replays, partial transcripts, turn-token mismatches, and transcripts already consumed by a closed-loop waiter stay excluded. Plivo renders an auto-response inside the next supported GetInput prompt so conversation continues after playback.

User Impact

Inbound voice conversations can continue beyond the first transcribed utterance across Telnyx-style webhooks and Plivo XML flows, without producing duplicate replies.

Evidence

  • Blacksmith Testbox focused suite: 93/93 tests passed across manager, outbound, webhook, and Plivo paths.
  • Post-review focused rerun: 48/48 webhook and Plivo tests passed.
  • Touched-surface check:changed: extension typechecks, lint, database-first guard, media helper guard, and import-cycle checks passed.
  • Real local TCP webhook path: HTTP 200, transcript persisted, exactly one response callback invoked.
  • Plivo XML checked against the current GetInput contract; nested Speak is supported and speechEndTimeout="2" is within the documented 2-10 second range.
  • Fresh Codex autoreview: clean, 0.91 confidence after fixing the one accepted Plivo contract finding.
  • Original contributor proof in fix(voice-call): auto-respond on the webhook event transcript path #79336 covered the real Telnyx call path. Co-authorship is preserved in the commit.

Known gap: no maintainer Plivo carrier credential was available for a billed PSTN call; provider-contract proof and the real XML generation path are covered directly.

@openclaw-barnacle openclaw-barnacle Bot added channel: voice-call Channel integration: voice-call size: M maintainer Maintainer-authored PR labels Jul 5, 2026
@clawsweeper

clawsweeper Bot commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed July 5, 2026, 5:43 AM ET / 09:43 UTC.

Summary
The branch routes voice-call webhook transcripts through a manager final-speech result, fires one auto-response for eligible final speech, adds Plivo listen-after-playback XML handling, and adds focused regression tests.

PR surface: Source +67, Tests +174. Total +241 across 11 files.

Reproducibility: yes. Source inspection shows current main's generic processParsedEvents only calls manager.processEvent, while manager call.speech records/listens and only the media-stream sibling calls handleInboundResponse; the linked issue and superseded PR add live Telnyx evidence.

Review metrics: 1 noteworthy metric.

  • Provider Playback Contract: 1 optional field added. The optional listenAfterPlayback hint extends the provider playback input shape and changes how carrier-owned listening resumes after TTS.

Stored data model
Persistent data-model change detected: vector/embedding metadata: extensions/voice-call/src/webhook.ts. Confirm migration or upgrade compatibility proof before merge.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #79118
Summary: This PR is the current replacement fix candidate for the canonical Telnyx generic webhook transcript auto-response bug; the older contributor PR is superseded by this refreshed branch.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge readiness
Overall: 🐚 platinum hermit
Proof: 🦞 diamond lobster
Patch quality: 🐚 platinum hermit
Result: ready for maintainer review.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • [P2] Clear or rerun the failing tooling CI shard before merge.
  • [P2] Decide whether Plivo shared-path proof is enough or a live Plivo call is required.

Risk before merge

  • [P1] Plivo is covered by source, XML contract, and regression tests but not by a billed carrier call; maintainers may still want to accept or require that proof before merge.
  • [P1] The exact PR head currently has one failing tooling CI shard outside the touched voice-call files, so normal merge validation still needs to be cleared.

Maintainer options:

  1. Accept Shared-Path Plivo Proof (recommended)
    Accept the Telnyx live proof plus Plivo contract/regression coverage and proceed once the unrelated-looking failing CI shard is cleared.
  2. Require Live Plivo Proof
    Hold merge until someone with Plivo credentials demonstrates one real Plivo speech-response turn after playback.

Next step before merge

  • No ClawSweeper repair is identified; maintainers should clear the failed tooling shard and make the merge call on the protected maintainer-labeled replacement PR.

Security
Cleared: No concrete security or supply-chain issue was found; the diff does not change dependencies, workflows, package metadata, or secret handling, and XML text is escaped before provider output.

Review details

Best possible solution:

Land this replacement after the exact-head validation issue is cleared, preserving the manager-result handoff and Plivo GetInput continuation while closing the older conflicting source PR as superseded.

Do we have a high-confidence way to reproduce the issue?

Yes. Source inspection shows current main's generic processParsedEvents only calls manager.processEvent, while manager call.speech records/listens and only the media-stream sibling calls handleInboundResponse; the linked issue and superseded PR add live Telnyx evidence.

Is this the best way to solve the issue?

Yes. Returning a closed final-speech result from manager while keeping response generation in the webhook server is the narrow owner-boundary fix; moving agent response work into manager events would couple state handling to runtime side effects.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 78685aec4686.

Label changes

Label changes:

  • add P1: The PR fixes a real voice-call workflow where carrier webhook transcripts are captured but no bot reply is spoken back to the caller.
  • add merge-risk: 🚨 message-delivery: The diff changes the generic voice-call webhook speech path that decides whether callers receive exactly one bot response after speaking.
  • add proof: sufficient: Contributor real behavior proof is sufficient. The PR body and superseded source PR include after-fix live Telnyx logs and a redacted persisted multi-turn transcript showing caller speech followed by audible bot replies.
  • add rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🦞 diamond lobster and patch quality is 🐚 platinum hermit.
  • add status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (logs): The PR body and superseded source PR include after-fix live Telnyx logs and a redacted persisted multi-turn transcript showing caller speech followed by audible bot replies.

Label justifications:

  • P1: The PR fixes a real voice-call workflow where carrier webhook transcripts are captured but no bot reply is spoken back to the caller.
  • merge-risk: 🚨 message-delivery: The diff changes the generic voice-call webhook speech path that decides whether callers receive exactly one bot response after speaking.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🦞 diamond lobster and patch quality is 🐚 platinum hermit.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (logs): The PR body and superseded source PR include after-fix live Telnyx logs and a redacted persisted multi-turn transcript showing caller speech followed by audible bot replies.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body and superseded source PR include after-fix live Telnyx logs and a redacted persisted multi-turn transcript showing caller speech followed by audible bot replies.
Evidence reviewed

PR surface:

Source +67, Tests +174. Total +241 across 11 files.

View PR surface stats
Area Files Added Removed Net
Source 6 95 28 +67
Tests 5 186 12 +174
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 11 281 40 +241

What I checked:

  • Current main missing generic handoff: On current main, the generic parsed-webhook path only calls manager.processEvent, while the media-stream sibling path separately calls handleInboundResponse; manager call.speech itself only records/transitions state. (extensions/voice-call/src/webhook.ts:958, 78685aec4686)
  • PR owner-boundary fix: The PR head makes manager.processEvent return a closed ProcessEventResult and lets the webhook server own the async auto-response side effect only for final speech that was not consumed by a transcript waiter. (extensions/voice-call/src/webhook.ts:959, 524a4c1d1632)
  • Replay/waiter regression coverage: PR tests assert dedupe replays return ignored, final speech reports waiterResolved, and mismatched turn-token speech remains ignored without resolving the waiter. (extensions/voice-call/src/manager.closed-loop.test.ts:133, 524a4c1d1632)
  • Plivo XML contract check: Official Plivo docs show GetInput supports nested Speak and speech input; the PR emits nested Speak inside GetInput with speechEndTimeout=2 and regression coverage for that XML shape. (extensions/voice-call/src/providers/plivo.ts:535, 524a4c1d1632)
  • Related issue and superseded PR: The current PR closes the canonical Telnyx no-reply issue and supersedes the older conflicting contributor PR, preserving that PR's live Telnyx proof in the body.
  • Feature history provenance: History shows the voice-call webhook/manager path was restored and later split by steipete, Plivo was introduced by vrknetha, and recent voice-call event/replay work was carried by vincentkoc. (extensions/voice-call/src/webhook.ts:425, 78685aec4686)

Likely related people:

  • steipete: Git history shows Peter Steinberger restored the voice-call webhook/Telnyx path and split the manager/event code that this PR changes; this PR also comes from that account with preserved co-authorship. (role: feature-history contributor and current replacement author; confidence: high; commits: 42c17adb5e4d, b5f7ba502de2, 524a4c1d1632; files: extensions/voice-call/src/webhook.ts, extensions/voice-call/src/manager/events.ts, extensions/voice-call/src/manager/outbound.ts)
  • vincentkoc: Recent voice-call replay, retry, and release-history work touched the same manager/events and provider webhook surfaces. (role: recent area contributor; confidence: medium; commits: e085fa1a3ffd, 20248c475f18, 0369bd75c1cd; files: extensions/voice-call/src/manager/events.ts, extensions/voice-call/src/providers/telnyx.ts, extensions/voice-call/src/webhook.ts)
  • vrknetha: History shows vrknetha introduced the Plivo provider and tests, which matter because this PR changes Plivo's GetInput/Speak continuation behavior. (role: provider-surface introducer; confidence: medium; commits: 946b0229e8a4, 2579609922dc; files: extensions/voice-call/src/providers/plivo.ts, extensions/voice-call/src/providers/plivo.test.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. P1 High-priority user-facing bug, regression, or broken workflow. merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. labels Jul 5, 2026
@steipete
steipete force-pushed the codex/pr-79336-land branch from 524a4c1 to ddfc9e2 Compare July 5, 2026 13:12
@steipete

steipete commented Jul 5, 2026

Copy link
Copy Markdown
Contributor Author

Land-ready maintainer proof:

  • Blacksmith Testbox focused voice-call suite: 93/93 passed; post-review Plivo/webhook rerun: 48/48 passed.
  • Touched-surface check:changed passed extension typechecks, lint, storage guards, and import cycles.
  • Real TCP webhook probe returned HTTP 200, persisted the transcript, and invoked exactly one response callback.
  • Official Plivo GetInput contract was inspected; the supported speechEndTimeout="2" value is regression-tested on both sibling paths.
  • Fresh Codex autoreview found no actionable findings at 0.91 confidence. Review artifacts validate with no findings.
  • Exact canonical head ddfc9e24ee705ffcfacab42e2cfcc1c418c290c5: hosted CI 28741948303 is the final gate; focused proof is unchanged from the canonicalized branch.
  • Proof gap: no maintainer Plivo credential for a duplicate billed PSTN call; official contract inspection, generated XML assertions, and the real local TCP path cover the changed branch.

@steipete
steipete merged commit c3b479b into main Jul 5, 2026
97 checks passed
@steipete
steipete deleted the codex/pr-79336-land branch July 5, 2026 13:21
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jul 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channel: voice-call Channel integration: voice-call maintainer Maintainer-authored PR merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. P1 High-priority user-facing bug, regression, or broken workflow. proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. size: M status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[voice-call] Telnyx inbound calls answer and greet, but bot never replies — auto-response loop missing for webhook call.speech path

1 participant