Skip to content

Conversation

@stephentoub
Copy link
Contributor

@stephentoub stephentoub commented Sep 22, 2025

Summary by CodeRabbit

  • New Features

    • Add support for hosted web search and code execution tools in requests.
    • Allow optional custom instructions to be included in system messages.
    • More flexible tool handling when building requests.
  • Improvements

    • Enhanced compatibility with updated tool/function declarations for more reliable parameter handling and schema interpretation.
  • Chores

    • Updated dependency to Microsoft.Extensions.AI.Abstractions v9.9.0.

@coderabbitai
Copy link

coderabbitai bot commented Sep 22, 2025

Walkthrough

Updates to MicrosoftExtensions.cs modify system instruction construction and overhaul tool handling to support AIFunctionDeclaration, HostedWebSearchTool, and HostedCodeInterpreterTool. The request.Tools assembly now separates function declarations from hosted tools. The csproj updates Microsoft.Extensions.AI.Abstractions to 9.9.0.

Changes

Cohort / File(s) Summary of changes
Request building and tool handling
src/GenerativeAI.Microsoft/Extensions/MicrosoftExtensions.cs
- SystemInstruction now includes derived system parts plus an additional Part from options.Instructions when present
- Tools processing classifies options.Tools into AIFunctionDeclaration, HostedWebSearchTool, HostedCodeInterpreterTool
- Builds FunctionDeclarations and Tool entries; attaches both to request.Tools as applicable
- Replaces OfType\<AIFunction\>() with OfType\<AIFunctionDeclaration\>() across schema lookup and content conversion paths
- Maps HostedWebSearchTool ➜ GoogleSearchTool; HostedCodeInterpreterTool ➜ CodeExecutionTool
Dependency version bump
src/GenerativeAI.Microsoft/GenerativeAI.Microsoft.csproj
Updated Microsoft.Extensions.AI.Abstractions from 9.8.0 to 9.9.0

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Caller
  participant MicrosoftExtensions as MicrosoftExtensions.ToGenerateContentRequest
  participant Options as options
  participant Request as GenerateContentRequest

  Caller->>MicrosoftExtensions: ToGenerateContentRequest(options)
  MicrosoftExtensions->>Options: Read system parts + Instructions
  rect rgba(230,240,255,0.5)
    note right of MicrosoftExtensions: Build SystemInstruction
    MicrosoftExtensions->>Request: Set SystemInstruction<br/>(system parts + optional Instructions Part)
  end

  MicrosoftExtensions->>Options: Iterate Tools
  alt Tool is AIFunctionDeclaration
    MicrosoftExtensions->>MicrosoftExtensions: Accumulate FunctionDeclarations
  else Tool is HostedWebSearchTool
    MicrosoftExtensions->>MicrosoftExtensions: Add Tool.GoogleSearch
  else Tool is HostedCodeInterpreterTool
    MicrosoftExtensions->>MicrosoftExtensions: Add Tool.CodeExecution
  end

  rect rgba(240,230,255,0.5)
    note right of MicrosoftExtensions: Assemble request.Tools
    MicrosoftExtensions->>Request: Set Tools { FunctionDeclarations?, Tools? }
  end

  MicrosoftExtensions-->>Caller: GenerateContentRequest
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

A nibble of code, a hop through the trees,
I bundled instructions with elegant ease.
New tools in my pouch—search and code play,
Functions declared in a tidy array.
I twitch my whiskers, content and bright—
Requests now leap just right. 🐇✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title correctly identifies a real change in the PR (bumping Microsoft.Extensions.AI.Abstractions to 9.9), but it does not reflect the substantial code changes in MicrosoftExtensions.cs (AIFunction → AIFunctionDeclaration refactors, new HostedWebSearchTool/HostedCodeInterpreterTool mappings, and system-instruction behavior updates), so it is only partially representative of the changeset. Because the title relates to an actual part of the changes but omits major functional edits, it is acceptable but could be clearer.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

👮 Agentic pre-merge checks are now available in preview!

Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.

  • Built-in checks – Quickly apply ready-made checks to enforce title conventions, require pull request descriptions that follow templates, validate linked issues for compliance, and more.
  • Custom agentic checks – Define your own rules using CodeRabbit’s advanced agentic capabilities to enforce organization-specific policies and workflows. For example, you can instruct CodeRabbit’s agent to verify that API documentation is updated whenever API schema files are modified in a PR. Note: Upto 5 custom checks are currently allowed during the preview period. Pricing for this feature will be announced in a few weeks.

Please see the documentation for more information.

Example:

reviews:
  pre_merge_checks:
    custom_checks:
      - name: "Undocumented Breaking Changes"
        mode: "warning"
        instructions: |
          Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).

Please share your feedback with us on this Discord post.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/GenerativeAI.Microsoft/Extensions/MicrosoftExtensions.cs (1)

98-123: Harden JSON schema parsing to avoid KeyNotFound and handle non‑object schemas.

GetProperty("properties") throws if absent; ValueKind can be Undefined; primitive/array schemas should still be converted.

-    if (schema.ValueKind == JsonValueKind.Null)
+    if (schema.ValueKind is JsonValueKind.Null or JsonValueKind.Undefined)
         return null;
-    else
-    {
-        var properties = schema.GetProperty("properties");
-        if (properties.GetPropertyCount() == 0)
-            return null;
-        else
-        {
-            var node = schema.AsNode();
-            if (node != null)
-            {
-                // Clone the node to avoid modifying the original schema
-                var clonedNode = node.DeepClone();
-                ApplySchemaTransformations(clonedNode);
-                return GoogleSchemaHelper.ConvertToCompatibleSchemaSubset(clonedNode);
-            }
-            return null;
-        }
-    }
+    if (schema.ValueKind != JsonValueKind.Object)
+    {
+        var node = schema.AsNode();
+        return node != null ? GoogleSchemaHelper.ConvertToCompatibleSchemaSubset(node) : null;
+    }
+    if (!schema.TryGetProperty("properties", out var properties) || properties.GetPropertyCount() == 0)
+        return null;
+    var node = schema.AsNode();
+    if (node == null) return null;
+    var clonedNode = node.DeepClone();
+    ApplySchemaTransformations(clonedNode);
+    return GoogleSchemaHelper.ConvertToCompatibleSchemaSubset(clonedNode);
🧹 Nitpick comments (2)
src/GenerativeAI.Microsoft/Extensions/MicrosoftExtensions.cs (2)

594-597: Avoid repeated schema lookups/serialization in recursive transformer.

Each recursion serializes function.JsonSchema and re‑looks up the function by name. Cache the function declaration and its JsonNode once per top‑level call or thread‑local context and thread it through recursive calls.

If you prefer minimal change: hoist the function lookup and JsonSerializer.SerializeToNode(...) above recursion and pass as an extra parameter.

Also applies to: 727-733, 777-783


1077-1109: Unify schema transformations to one path.

ApplySchemaTransformations and s_schemaTransformerCache perform overlapping format rewrites. Prefer one mechanism (ideally the cache) to prevent drift.

Would you like a follow‑up diff to route ParseFunctionParameters through s_schemaTransformerCache?

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d61044c and 2a1c486.

📒 Files selected for processing (2)
  • src/GenerativeAI.Microsoft/Extensions/MicrosoftExtensions.cs (5 hunks)
  • src/GenerativeAI.Microsoft/GenerativeAI.Microsoft.csproj (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/GenerativeAI.Microsoft/Extensions/MicrosoftExtensions.cs (5)
src/GenerativeAI/Types/ContentGeneration/Inputs/Content.cs (4)
  • Content (11-58)
  • Content (16-19)
  • Content (25-29)
  • Content (40-44)
src/GenerativeAI.Tools/Helpers/FunctionSchemaHelper.cs (1)
  • FunctionDeclaration (21-61)
src/GenerativeAI.Tools/GenericFunctionTool.cs (1)
  • Tool (41-52)
src/GenerativeAI/Types/ContentGeneration/Tools/GoogleSearch/GoogleSearchTool.cs (1)
  • GoogleSearchTool (7-10)
src/GenerativeAI/Types/ContentGeneration/Tools/CodeExecution/CodeExecutionTool.cs (1)
  • CodeExecutionTool (8-11)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build (9.0.x)
🔇 Additional comments (2)
src/GenerativeAI.Microsoft/Extensions/MicrosoftExtensions.cs (1)

48-93: Tools assembly looks correct; confirm request.Tools shape matches API.

Collecting FunctionDeclarations into a single Tool and adding hosted GoogleSearch/CodeExecution tools aligns with the Gemini Tool model.

Please validate at runtime that the resulting JSON matches the API (function_declarations grouped under a single tool, separate entries for google_search/code_execution). If helpful, log the serialized request in a dev build.

src/GenerativeAI.Microsoft/GenerativeAI.Microsoft.csproj (1)

35-35: Version bump to 9.9.0 — verify API alignment across repo

NuGet/docs confirm Microsoft.Extensions.AI.Abstractions v9.9.0 exposes AIFunction/AIFunctionDeclaration and hosted-tool helpers; the repository scan didn't run (rg reported "No files were searched"). Re-run a repo-wide search and confirm there are no remaining references to pre-9.9 types (AIFunction, AIFunctionDeclaration, Hosted*Tool) and that CI uses an SDK including 9.9 APIs.

Suggested search:
rg -nP -C2 --hidden --no-ignore -S '\bAIFunction\b|\bAIFunctionDeclaration\b|Hosted(OpenAI|Bing|Search)Tool\b' --glob '!/bin/' --glob '!/obj/'

Comment on lines +36 to 39
if (systemParts.Length > 0 || !string.IsNullOrWhiteSpace(options?.Instructions))
{
request.SystemInstruction = new Content(systemParts, Roles.System);
request.SystemInstruction = new Content(systemParts.Concat([new Part { Text = options!.Instructions }]), Roles.System);
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix NRE when options is null; append instructions only when present.

If systemParts.Length > 0 and options is null, options!.Instructions dereferences null. Also avoid appending an empty instruction.

Apply:

-        if (systemParts.Length > 0 || !string.IsNullOrWhiteSpace(options?.Instructions))
-        {
-            request.SystemInstruction = new Content(systemParts.Concat([new Part { Text = options!.Instructions }]), Roles.System);
-        }
+        if (systemParts.Length > 0 || !string.IsNullOrWhiteSpace(options?.Instructions))
+        {
+            IEnumerable<Part> sys = systemParts;
+            if (!string.IsNullOrWhiteSpace(options?.Instructions))
+            {
+                sys = sys.Concat(new[] { new Part { Text = options!.Instructions! } });
+            }
+            request.SystemInstruction = new Content(sys.ToArray(), Roles.System);
+        }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (systemParts.Length > 0 || !string.IsNullOrWhiteSpace(options?.Instructions))
{
request.SystemInstruction = new Content(systemParts, Roles.System);
request.SystemInstruction = new Content(systemParts.Concat([new Part { Text = options!.Instructions }]), Roles.System);
}
if (systemParts.Length > 0 || !string.IsNullOrWhiteSpace(options?.Instructions))
{
IEnumerable<Part> sys = systemParts;
if (!string.IsNullOrWhiteSpace(options?.Instructions))
{
sys = sys.Concat(new[] { new Part { Text = options!.Instructions! } });
}
request.SystemInstruction = new Content(sys.ToArray(), Roles.System);
}
🤖 Prompt for AI Agents
In src/GenerativeAI.Microsoft/Extensions/MicrosoftExtensions.cs around lines
36–39, the current code dereferences options with options! and always appends
options.Instructions which causes a NullReferenceException when options is null
and can append empty instructions; change the conditional logic to only access
options.Instructions when options is not null and not whitespace, build the
SystemInstruction parts sequence so that you only concatenate an instruction
Part when that check passes (otherwise use systemParts alone), and avoid forcing
a null-forgiving operator.

@gunpal5 gunpal5 merged commit 54da332 into gunpal5:main Sep 29, 2025
2 checks passed
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.

2 participants