-
Notifications
You must be signed in to change notification settings - Fork 839
Add TextReasoningContent.ProtectedData #6784
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
cc: @tghamm |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR adds a new ProtectedData
property to TextReasoningContent
to support provider-specific opaque data blobs that need to be roundtripped but aren't intended for human consumption. This enables support for encrypted reasoning traces, signature blobs, and redacted content from various AI providers like OpenAI, Anthropic, AWS Bedrock, and Gemini.
Key changes:
- Adds nullable
ProtectedData
string property toTextReasoningContent
- Updates OpenAI integration to handle encrypted content in reasoning responses
- Modifies content coalescing logic to prevent merging when protected data is present
Reviewed Changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.
Show a summary per file
File | Description |
---|---|
TextReasoningContent.cs |
Adds the new ProtectedData property with comprehensive documentation |
OpenAIResponsesChatClient.cs |
Updates OpenAI integration to map encrypted content to/from the new property |
ChatResponseExtensions.cs |
Modifies coalescing logic to respect protected data boundaries |
TextReasoningContentTests.cs |
Adds test coverage for the new property |
Microsoft.Extensions.AI.Abstractions.json |
Registers the new property as stable API |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
src/Libraries/Microsoft.Extensions.AI.Abstractions/ChatCompletion/ChatResponseExtensions.cs
Show resolved
Hide resolved
07ec1ba
to
6780f20
Compare
Fixes #6510
I considered multiple approaches, including having a separate content type dedicated to encrypted/redacted/protected data, but ended up just extending the existing TextReasoningContent with a new optional ProtectedData property.
Anthropic has thinking content, which is human-readable text that's accompanied by an opaque "signature" blob: that's representable with the thinking as Text and the signature as ProtectedData. It also has redacted thinking content, which is just an opaque data string, which we can represent with empty Text and data as ProtectedData.
OpenAI lets users of the Responses API opt-in to including an encrypted version of the reasoning trace in their output, which is most useful when the developer also opts-out of storing the responses in the service and thus needs to roundtrip the data back. By default, reasoning output only includes human-readable text, but if opted into encrypted reasoning, the output items will typically include both the summary human-readable text and the encrypted data. That can be modeled using Text for the summary (as we do today) and ProtectedData for the encrypted content.
AWS Bedrock exposes reasoning via a ReasoningContentBlock, which has both reasoningText (human readable) and reasoningContent (opaque encrypted content). However, it'll only ever use one of them in each instance, so we can end up with either Text being non-empty or ProtectedData being non-null.
Gemini has a Part that has both a thought (human readable) and thoughtSignature (opaque data), which we can represent as Text and ProtectedData, respectively.
The one thing gnawing at me is that we have Text right now as always returning a non-null string: if you give it null, it gives you back empty. That means the only way we have to distinguish "only ProtectedData" from "Text and ProtectedData" is if Text is empty. Other than bugs, I don't think there are real situations where one of these services sends back empty Text, but if we find that can happen, we might either need to take a (non-binary breaking) change to have Text be nullable, or add some sort of additional property to the instance that specifies what kind of data it carries.
Microsoft Reviewers: Open in CodeFlow