Repository navigation
fix: clarify ForceEndTurn deployment behavior - #788
Conversation
|
dg-coreylweathers
left a comment
There was a problem hiding this comment.
What this PR does
Changes the ForceEndTurn examples and the conversational-STT skill file to say the control is available on Deepgram-hosted deployments including EU and AU (self-hosted depends on the release), makes the Voice Agent example fail fast on FORCE_END_TURN_UNSUPPORTED, and edits the manual-patch ledger.
What I checked
- Is the availability claim true? Yes: the repo's own
tests/manual/listen/v2/force_end_turn/main.pypassed all four steps withtrigger: manualagainstapi.deepgram.com,api.eu.deepgram.com, andapi.au.deepgram.com. - Is
FORCE_END_TURN_UNSUPPORTEDreal? Yes, it is the Voice Agent warning for a non-Flux listen provider (deepgram-docsschemas.agent.v1.yml:220), and both Warning and Error carry.code/.description. - Gates in Docker: mypy clean, ruff clean on changed files, pytest 1034 passed.
Blocking
- The
AGENTS.md/.fernignorehunk forlisten_v2eot_threshold.pyandrequests/deepgram_listen_provider_v2.pyis stale: main'sAGENTS.md:85already says Fern emits that description natively as of the 2026-09-23 regen and the files were unfrozen, so main's.fernignoreno longer lists them. The branch is also CONFLICTING. Fix: rebase onto main and drop that hunk entirely; keep only the StrictInt unfreeze-condition change.
Should-fix
- "Self-hosted availability depends on the deployed release" (
examples/16:24-25,SKILL.md:94) omits the switch. deepgram-docs says it needslisten_v2_force_end_turn = trueunder[features]on the 2026-09-15 release or later. Say that. tests/manual/listen/v2/force_end_turn/main.py:24-27,174andasync.py:8,115still say "gated per deployment" / "not enabled on this deployment"; align them with the new sentence.
Nit: examples/32:94-104, the trailing rejected-check can raise after agent_finished is set; fine if intended, worth a comment.
a46bb3b to
3836a89
Compare
dg-coreylweathers
left a comment
There was a problem hiding this comment.
Requesting changes for two should-fixes and three small cleanups. Everything the PR claims checked out live; these are about the text and the example around it.
What this PR does: ForceEndTurn is a message that lets an app end a speaker's turn right away instead of waiting for Flux to detect it. The examples and manual tests used to call it "gated per deployment." They now say it works on Deepgram-hosted US, EU and AU, and that self-hosted customers need the 2026-09-15 release plus listen_v2 = true and listen_v2_force_end_turn = true under [features]. The Voice Agent example now stops at once on FORCE_END_TURN_UNSUPPORTED instead of timing out after 15 seconds.
What I checked:
- Hosted availability: I ran
tests/manual/listen/v2/force_end_turn/async.pytoday against api.deepgram.com, api.eu.deepgram.com and api.au.deepgram.com. All three returnedEndOfTurnwithtrigger="manual". - Self-hosted claim:
release-260915shipped on 2026-09-15 with Flux Forced End-of-Turn. The flag names match what the self-hosted team gave on 9/4. - Voice Agent example: it completes against prod with Flux. With a Nova-3 listener it raises
FORCE_END_TURN_UNSUPPORTEDafter 2 seconds. - Tests and lint: the new test passes, ruff is clean, and CI is green on 3.10–3.13.
Please fix:
reference.md:5417still says "Requires server-side enablement; deployments without the feature reject the message and close the connection," so a hosted developer reads it as "this may not work for me." Replace it with:
- Available on Deepgram-hosted deployments (including EU and AU). Self-hosted deployments need the 2026-09-15 release or later with the ForceEndTurn feature enabled; unsupported deployments reply UNPARSABLE_CLIENT_MESSAGE and close the connection- Delete the "Link the frozen EOT description patch to deepgram-docs #1202" bullet from the PR description. Nothing in the diff makes that change.
examples/16-transcription-force-end-turn.py:59: the docstring still says "Because ForceEndTurn is gated … point it at a deployment that has the feature." Suggested: "Accepts DEEPGRAM_BASE_URL=wss:// so it can target a regional or self-hosted deployment. Defaults to production."examples/32-voice-agent-force-end-turn.py:125: raising inside thewithblock also prints "Connection error: sent 1011 (internal error)" after the real error. Record the failure, leave thewithblock, then raise.examples/32-voice-agent-force-end-turn.py:96-97: the new lines add two mypyattr-definederrors becausemessageis typedobject. Typing the callback parameter astyping.Anyclears them.
Open question (not blocking): the 9/4 thread in #engineering-self-hosted-releases that names the listen_v2_force_end_turn flag also planned to remove it. If a later self-hosted release drops the flag, "2026-09-15 or later with listen_v2_force_end_turn = true" will be wrong for newer releases. Do you know whether that removal has shipped?
dfec20b to
715f194
Compare
|
Addressed the lifecycle coverage feedback in 5798467.
@dg-coreylweathers Could you re-review? |
dg-coreylweathers
left a comment
There was a problem hiding this comment.
Approving. All nine items from my two earlier reviews are fixed in the code, and the example behaves as described against the live API.
What this PR does: ForceEndTurn lets an app end a speaker's turn right away. The examples, manual tests, reference.md and the skill file now say it works on Deepgram-hosted US, EU and AU, and that self-hosted needs the 2026-09-15 release plus listen_v2 = true and listen_v2_force_end_turn = true under [features]. The Voice Agent example now stops at once on FORCE_END_TURN_UNSUPPORTED.
What I checked:
- Does the Voice Agent example stop on rejection? Yes. With a Nova-3 listener on prod (request 01a1461c-6cdb-7913-8741-8b7a4dd5b951) it printed the warning, raised
RuntimeErrorwith exit code 1, and printed no "Connection error: sent 1011" line. With Flux (01a1461c-7537-70e1-8673-a0b649211ddb) it completed with exit 0. - Does the new test catch the bug? Yes. Against main's version of the example both tests fail, one with "DID NOT RAISE RuntimeError" (a false success after
AgentAudioDone). Against the version from my last review, the context-exit test fails. - Is the self-hosted flag still required? Yes, as of 2026-10-15. Linear API-75 plans to remove it; when that ships, these five sentences need an update.
- mypy is clean on example 32, ruff is clean, and CI is green on 3.10–3.13.
Nits fixed in 1db8e8a: AGENTS.md:45 and example 16's comments now say "unsupported deployment" instead of "gated"; example 32 raises both timeouts after the connection closes, so a timeout no longer prints a "1011" connection error; ruff format applied. The example tests still pass (2 of 2), and ruff, ruff format and mypy are clean. The PR body now lists the StrictInt unfreeze change, the new test, and pytest/mypy.
Merge note: this conflicts with #789 in AGENTS.md (both edit the agent/v1/socket_client.py line). Keep #789's line, then this PR's StrictInt line below it.
Replace remaining "gated" wording with unsupported-deployment phrasing, raise example 32 timeouts after the connection closes so they no longer print a spurious 1011 connection error, and apply ruff format. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1db8e8a to
70cf2e9
Compare
dg-coreylweathers
left a comment
There was a problem hiding this comment.
Re-approving. My earlier approval was dismissed by the rebase onto main; nothing new was added. Commits 2–7 are identical to what I approved, and commit 1 changed only where AGENTS.md and .fernignore collided with #789 and #803. Both of those PRs' lines are still there.
What I checked:
- Does the new main break anything? No. #789 only adds send_raw(), which the Voice Agent example and its test never call, and #803 doesn't touch the Listen V2 code the examples use. In Docker, tests/custom gives 960 passed and 1 skipped, the new test passes 2 of 2, ruff and mypy are clean, and CI is green on 3.10–3.13.
- Is "available on Deepgram-hosted deployments" true for India too? Yes. tests/manual/listen/v2/force_end_turn/async.py against wss://api.in.deepgram.com returned EndOfTurn with trigger='manual'.
Nits (non-blocking):
- tests/manual/listen/v2/force_end_turn/async.py:93 still says "A gated deployment closes the socket". Suggested: "A deployment without ForceEndTurn closes the socket rather than ignoring the message,"
- Optional: name India alongside EU and AU.
Follow-up: if Linear API-75 removes the listen_v2_force_end_turn flag in a self-hosted release, the self-hosted sentences in these files will need updating.
dg-coreylweathers
left a comment
There was a problem hiding this comment.
Approving; details in the review above.
🤖 I have created a release *beep* *boop* --- ## [7.14.0](v7.13.0...v7.14.0) (2026-10-20) ### Features * **Voice Agent:** Send protocol-transparent control frames with sync or async `connection.send_raw(...)`. Dictionary payloads are serialized without model validation; pre-serialized JSON strings are sent unchanged. * **Listen V1:** Receive typed `ListenV1ConfigureSuccess` and `ListenV1ConfigureFailure` responses after `connection.send_configure(ListenV1Configure(...))`, including failure codes for unsupported or over-limit keyterms. ### Bug Fixes * **Voice Agent:** Clarify ForceEndTurn availability for hosted and self-hosted deployments. The example now reports `FORCE_END_TURN_UNSUPPORTED` and waits for the final outcome before closing the connection. ## Validation - Source PR CI passed across Python 3.10 through 3.13. - #803: `poetry run pytest` passed with 1,075 tests and 4 skips; mypy and Ruff passed. - #789: targeted socket-client tests, mypy, and Ruff passed. - #788: ForceEndTurn regression coverage passed. --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Greg Holmes <greg.holmes@deepgram.com>
Summary
expressivitypatch's unfreeze condition in.fernignoreand AGENTS.md.tests/custom/test_voice_agent_force_end_turn_example.pycovering the late-rejection wait and the leave-context-before-raising path.Validation