Skip to content

Preserve tool outcomes and fix streamed call assembly - #1349

Merged
Quim Muntal (qmuntal) merged 1 commit into
mainfrom
fix/preserve-tool-call-outcomes
Nov 3, 2026
Merged

Quim Muntal (qmuntal) merged 1 commit into
mainfrom
fix/preserve-tool-call-outcomes

Conversation

@qmuntal

Copy link
Copy Markdown
Member

Summary

Fix the SDK behavior behind the streaming and cancellation workarounds documented in dkr290/agenticgo#49.

  • Assemble complete streamed tool calls and refusals once the OpenAI stream finishes successfully; preserve text, usage, metadata, and the original raw chunks.
  • Emit completed and unexecuted tool outcomes before terminal errors, including concurrent batches, approval resumption, and buffered non-streaming runs. Preserve original tool errors.
  • Keep non-streaming buffering and ResponseStream.Collect error behavior unchanged. No new public APIs or options.
  • Document existing per-call history support for injected images and test typed, serialized external storage without session in-memory history or duplicated messages.

.NET comparison

Checked stable Agent Framework dotnet-1.27.0 (4d1674b78951d6fd127ada532660514637f906e9), which uses Microsoft.Extensions.AI 10.10.0 and its OpenAI adapter 10.10.1.

Validation

  • Full suites passed: provider/openaiprovider, agent/harness/toolautocall, and agent.
  • Regression coverage includes packed terminal calls, interleaved arguments, terminal refusals, failed streams, completed side effects during cancellation, panics, concurrent dispatch, approvals, middleware reuse, and serialized image history.
  • Configured gofumpt applied; compatible golangci-lint reports 0 new issues. Full-package lint has three pre-existing formatting findings in unchanged files.

Assemble complete streamed tool calls and refusals after successful stream
completion. Preserve completed and unexecuted tool outcomes before terminal
errors, including buffered runs, concurrent batches, and approval resumption.

Document per-call image history and add regression coverage without changing
non-streaming defaults or introducing new public APIs.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings November 3, 2026 10:14
@qmuntal
Quim Muntal (qmuntal) requested a review from a team as a code owner November 3, 2026 10:14
@github-actions github-actions Bot added area:agent Changes files in the agent area area:provider Changes files in the provider area area:provider/openai Changes files in the provider / openai area labels Nov 3, 2026
@github-actions

github-actions Bot commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

API consistency review

Result Scope
unable to determine user-visible behavior

Changed Go contract

No exported API changes (per the PR description). Observable behavior changes:

  • The OpenAI provider now assembles streamed tool calls and refusals once the stream finishes.
  • toolautocall and the agent now emit completed and unexecuted tool outcomes before terminal errors.
  • Non-streaming buffering and ResponseStream.Collect error behavior are unchanged.

Upstream evidence reviewed

No upstream sources were independently reviewed in this run. The PR description cites the .NET MEAI OpenAI adapter and FunctionInvokingChatClient, but I did not verify those references.

Assessment

I could not complete a verified comparison with the .NET and Python implementations, so I am reporting no findings. The PR states that Go deliberately preserves partial tool outcomes on cancellation, where .NET lets the exception escape before building the batch result. Maintainers should confirm that this divergence is acceptable and check the Python OpenAI streaming tool-call handling manually. No parity label was added.

Generated by Go API Consistency Review Agent for #1349 · copilot · auto · 14 AIC · ⌖ 0.616 AIC · ⊞ 4.9K · ◷

@qmuntal
Quim Muntal (qmuntal) added this pull request to the merge queue Nov 3, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Unresolved issues allow truncated OpenAI streams to trigger execution of unfinished tool calls and tool-loop failures to label messages with stale conversation IDs.

2 open issues
What changed in this PR

This PR improves streamed OpenAI response assembly and preserves partial tool outcomes when automatic invocation stops, without adding public APIs.

Changes:

  • Assemble tool calls and refusals after streaming ends, preserving text, usage, metadata, and raw chunks.
  • Emit completed and unexecuted tool outcomes before terminal errors, including buffered runs and approval resumption.
  • Document and test injected-image retention through serialized external history.
File Description
provider/​openaiprovider/​chat.go Emit accumulated tool calls and refusals after streaming.
provider/​openaiprovider/​chat_test.go Cover packed calls, interleaved arguments, refusals, and stream failures.
docs/​agent-harness.md Explain partial outcomes, cancellation, and external history.
agent/​messageinjection.go Document persistence requirements for injected content.
agent/​messageinjection_test.go Test serialized image history across tool rounds.
agent/​harness/​toolautocall/​autocall.go Preserve tool outcomes and buffered updates before terminal errors.
agent/​harness/​toolautocall/​autocall_test.go Cover cancellation, approvals, concurrent outcomes, and provider failures.

Review effort: Balanced

if len(acc.Choices) == 0 {
return
}
choice := acc.Choices[0]
Comment on lines +209 to +211
if runErr == nil {
response.ConversationID = finalConversationID
}
Merged via the queue into main with commit 5d16802 Nov 3, 2026
24 checks passed
@qmuntal
Quim Muntal (qmuntal) deleted the fix/preserve-tool-call-outcomes branch November 3, 2026 10:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:agent Changes files in the agent area area:provider/openai Changes files in the provider / openai area area:provider Changes files in the provider area

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants