Skip to content

voice: drop workflow dependency, drive turns via agent.Run + engine.Engine [skip-tag:voice]#58

Merged
lIang70 merged 1 commit into
mainfrom
fix/voice-remove-workflow-dep
May 7, 2026
Merged

voice: drop workflow dependency, drive turns via agent.Run + engine.Engine [skip-tag:voice]#58
lIang70 merged 1 commit into
mainfrom
fix/voice-remove-workflow-dep

Conversation

@lIang70

@lIang70 lIang70 commented May 7, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • voice.Pipeline no longer imports sdk/workflow. Turns are now driven by agent.Run against any engine.Engine; the pipeline installs an internal voiceHost to capture stream-delta envelopes for the active runID and translate them into voice.Events.
  • New options: WithEngineHost(engine.Host) (fan-out for OTel / event bus / interrupts / checkpointer) and WithRunOptions(...agent.RunOption) (escape hatch for agent.BoardSeeder, observers, deciders, attributes — including history loading, which is no longer a pipeline concern).
  • Removed: WithTurnHistory, WithContextID. Session.pipelineForTurn no longer copies sessionID into a pipeline-level context field.
  • voice/go.mod: sdk v0.2.2v0.2.7 (needed for agent.Run and engine.StreamDeltaPayload).

Why [skip-tag:voice]

This is a breaking change to voice's public NewPipeline signature and option surface. Auto-tag's patch-only bump would label it incorrectly. The release coordinator should hand-tag voice/v0.2.0 after merge.

Migration

Old:
```go
voice.NewPipeline(s, t, workflowRuntime, workflowAgent,
voice.WithTurnHistory(msgs),
voice.WithContextID("sess-1"),
)
```

New:
```go
voice.NewPipeline(s, t, engineImpl, agent.Agent{ID: "voice"},
voice.WithRunOptions(
agent.WithBoardSeed(historySeeder(msgs)),
agent.WithAttributes(map[string]string{"context_id": "sess-1"}),
),
)
```

For graph-based agents, the engine is runner.New(def, factory) from sdk/graph/runner (it satisfies engine.Engine directly).

Verification

Check Result
`go vet ./voice/...`
`rg workflow voice/` ✅ 0 hits
`go list -deps ./voice/... | grep workflow` (feat) ✅ 0 hits
`go list -deps ./voice/... | grep workflow` (main) exists, confirms removal works
`go test ./voice/... -race -count=1` ✅ 13/13 packages
`go test ./voice/. -count=20` ✅ no flake
Test function names diff (main vs feat) ✅ identical — no coverage loss
`go test ./sdk/...` ✅ unaffected
`GOWORK=off go test ./voice/... -count=1` (against released sdk v0.2.7)

Bug found & fixed during refactor

`agent.Run` returns `(res, nil)` for engine-side failures (errors land on `res.Err` + non-completed `res.Status`), unlike the old `workflow.Runtime.Run` which returned the error directly. The naive port lost `EventError` emission for runner failures; `TestPipeline_RunnerError` caught it and `startFlow` now reads both `err` and `res.Err`, while filtering out cancelled/interrupted statuses to preserve Abort behaviour.

Out of scope (intentional)

  • `examples/voice-pipeline/` is pinned to released `voice v0.1.0` and `sdk v0.2.0`; updating it would touch unrelated API drift (`llm.ProviderConfigStore`, `node.NewFactory` …). It will be migrated in a follow-up PR after `voice/v0.2.0` is published.

Test plan

  • CI green
  • Manual review of `voiceHost` Publisher fan-out logic in `voice/pipeline.go`
  • Manual review of error-classification switch in `startFlow`
  • Confirm `[skip-tag:voice]` is honoured by `auto-tag` workflow on merge

Made with Cursor

…ngine [skip-tag:voice]

NewPipeline now takes (engine.Engine, agent.Agent) instead of
(workflow.Runtime, workflow.Agent). The pipeline installs an internal
voiceHost that captures stream-delta envelopes for the active runID
and converts them to voice events; non-stream Host methods delegate
to an optional caller-supplied host (WithEngineHost).

History injection is no longer a pipeline concern. WithTurnHistory /
WithContextID are removed; callers wire history through an
agent.BoardSeeder via the new WithRunOptions(...) escape hatch.

Tests rewritten on top of engine.Engine fakes that publish stream
deltas via engine.EmitStream{Token,ToolCall,ToolResult}. The set of
test functions is unchanged — only the fakes were translated to the
new stack.

Session no longer copies sessionID into a pipeline contextID field
(that field is gone); callers that need agent.Request.ContextID can
attach it via WithRunOptions + agent.WithAttributes.

voice/go.mod bumped from sdk v0.2.2 to v0.2.7 to pull in the agent +
engine packages required by the new wiring.

Carries [skip-tag:voice] because this is a breaking change to voice's
public NewPipeline / option surface; auto-tag's patch-only logic
would label it incorrectly. Release coordinator should hand-tag
voice/v0.2.0.

Co-authored-by: Cursor <cursoragent@cursor.com>
@lIang70
lIang70 merged commit c029296 into main May 7, 2026
7 checks passed
@lIang70
lIang70 deleted the fix/voice-remove-workflow-dep branch May 7, 2026 03:35
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