diff --git a/readme.md b/readme.md index d7304ee..52fd5e6 100644 --- a/readme.md +++ b/readme.md @@ -325,104 +325,170 @@ configuration without restarting the application. ## Grok -Full support for Grok [Live Search](https://docs.x.ai/docs/guides/live-search) -and [Reasoning](https://docs.x.ai/docs/guides/reasoning) model options. +Full support for Grok new [agentic tools](https://docs.x.ai/docs/guides/tools/overview): + +### Web Search ```csharp -// Sample X.AI client usage with .NET var messages = new Chat() { - { "system", "You are a highly intelligent AI assistant." }, - { "user", "What is 101*3?" }, + { "system", "You are an AI assistant that knows how to search the web." }, + { "user", "What's Tesla stock worth today? Search X and the news for latest info." }, }; -var grok = new GrokChatClient(Environment.GetEnvironmentVariable("XAI_API_KEY")!, "grok-3-mini"); +var grok = new GrokClient(Environment.GetEnvironmentVariable("XAI_API_KEY")!).AsIChatClient("grok-4.1-fast"); -var options = new GrokChatOptions +var options = new ChatOptions { - ModelId = "grok-4-fast-reasoning", // 👈 can override the model on the client - Temperature = 0.7f, - ReasoningEffort = ReasoningEffort.High, // 👈 or Low - Search = GrokSearch.Auto, // 👈 or On/Off + Tools = [new HostedWebSearchTool()] // 👈 compatible with OpenAI }; var response = await grok.GetResponseAsync(messages, options); ``` -Search can alternatively be configured using a regular `ChatOptions` -and adding the `HostedWebSearchTool` to the tools collection, which -sets the live search mode to `auto` like above: +In addition to basic web search as shown above, Grok supports more +[advanced search](https://docs.x.ai/docs/guides/tools/search-tools) scenarios, +which can be opted-in by using Grok-specific types: ```csharp -var messages = new Chat() -{ - { "system", "You are an AI assistant that knows how to search the web." }, - { "user", "What's Tesla stock worth today? Search X and the news for latest info." }, -}; +var grok = new GrokChatClient(Environment.GetEnvironmentVariable("XAI_API_KEY")!).AsIChatClient("grok-4.1-fast"); +var response = await grok.GetResponseAsync( + "What are the latest product news by Tesla?", + new ChatOptions + { + Tools = [new GrokSearchTool() + { + AllowedDomains = [ "ir.tesla.com" ] + }] + }); +``` -var grok = new GrokChatClient(Environment.GetEnvironmentVariable("XAI_API_KEY")!, "grok-3"); +You can alternatively set `ExcludedDomains` instead, and enable image +understanding with `EnableImageUndestanding`. Learn more about these filters +at [web search parameters](https://docs.x.ai/docs/guides/tools/search-tools#web-search-parameters). -var options = new ChatOptions +### X Search + +In addition to web search, Grok also supports searching on X (formerly Twitter): + +```csharp +var response = await grok.GetResponseAsync( + "What's the latest on Optimus?", + new ChatOptions + { + Tools = [new GrokXSearchTool + { + // AllowedHandles = [...], + // ExcludedHandles = [...], + // EnableImageUnderstanding = true, + // EnableVideoUnderstanding = true, + // FromDate = ..., + // ToDate = ..., + }] + }); +``` + +Learn more about available filters at [X search parameters](https://docs.x.ai/docs/guides/tools/search-tools#x-search-parameters). + +You can combine both web and X search in the same request by adding both tools. + +### Code Execution + +The code execution tool enables Grok to write and execute Python code in real-time, +dramatically expanding its capabilities beyond text generation. This powerful feature +allows Grok to perform precise calculations, complex data analysis, statistical +computations, and solve mathematical problems that would be impossible through text alone. + +This is Grok's equivalent of the OpenAI code interpreter, and is configured the same way: + +```csharp +var grok = new GrokClient(Configuration["XAI_API_KEY"]!).AsIChatClient("grok-4-fast"); +var response = await grok.GetResponseAsync( + "Calculate the compound interest for $10,000 at 5% annually for 10 years", + new ChatOptions + { + Tools = [new HostedCodeInterpreterTool()] + }); + +var text = response.Text; +Assert.Contains("$6,288.95", text); +``` + +If you want to access the output from the code execution, you can add that as an +include in the options: + +```csharp +var grok = new GrokClient(Configuration["XAI_API_KEY"]!).AsIChatClient("grok-4-fast"); +var options = new GrokChatOptions { - Tools = [new HostedWebSearchTool()] // 👈 equals setting GrokSearch.Auto + Include = { IncludeOption.CodeExecutionCallOutput }, + Tools = [new HostedCodeInterpreterTool()] }; -var response = await grok.GetResponseAsync(messages, options); +var response = await grok.GetResponseAsync( + "Calculate the compound interest for $10,000 at 5% annually for 10 years", + options); + +var content = response.Messages + .SelectMany(x => x.Contents) + .OfType() + .First(); + +foreach (AIContent output in content.Outputs) + // process outputs from code interpreter ``` -We also provide an OpenAI-compatible `WebSearchTool` that can be used to restrict -the search to a specific country in a way that works with both Grok and OpenAI: +Learn more about the [code execution tool](https://docs.x.ai/docs/guides/tools/code-execution-tool). + +### Collection Search + +If you maintain a [collection](https://docs.x.ai/docs/key-information/collections), +Grok can perform semantic search on it: ```csharp var options = new ChatOptions { - Tools = [new WebSearchTool("AR")] // 👈 search in Argentina + Tools = [new HostedFileSearchTool { + Inputs = [new HostedVectorStoreContent("[collection_id]")] + }] }; ``` -This is equivalent to the following when used with a Grok client: +Learn more about [collection search](https://docs.x.ai/docs/guides/tools/collections-search-tool). + +### Remote MCP + +Remote MCP Tools allow Grok to connect to external MCP (Model Context Protocol) servers. +This example sets up the GitHub MCP server so queries about releases (limited specifically +in this case): + ```csharp var options = new ChatOptions { - // 👇 search in Argentina - Tools = [new GrokSearchTool(GrokSearch.On) { Country = "AR" }] + Tools = [new HostedMcpServerTool("GitHub", "https://api.githubcopilot.com/mcp/") { + AuthorizationToken = Configuration["GITHUB_TOKEN"]!, + AllowedTools = ["list_releases"], + }] }; ``` -### Advanced Live Search - -To configure advanced live search options, beyond the `On|Auto|Off` settings -in `GrokChatOptions`, you can use the `GrokSearchTool` instead, which exposes -the full breath of [live search options](https://docs.x.ai/docs/guides/live-search) -available in the Grok API. +Just like with code execution, you can opt-in to surfacing the MCP outputs in +the response: ```csharp -var options = new ChatOptions +var options = new GrokChatOptions { - Tools = [new GrokSearchTool(GrokSearch.On) - { - FromDate = new DateOnly(2025, 1, 1), - ToDate = DateOnly.FromDateTime(DateTime.Now), - MaxSearchResults = 10, - Sources = - [ - new GrokWebSource - { - AllowedWebsites = - [ - "https://catedralaltapatagonia.com", - "https://catedralaltapatagonia.com/parte-de-nieve/", - "https://catedralaltapatagonia.com/tarifas/" - ] - }, - ] + // Exposes McpServerToolResultContent in responses + Include = { IncludeOption.McpCallOutput }, + Tools = [new HostedMcpServerTool("GitHub", "https://api.githubcopilot.com/mcp/") { + AuthorizationToken = Configuration["GITHUB_TOKEN"]!, + AllowedTools = ["list_releases"], }] }; + ``` -> [!TIP] -> You can configure multiple sources including `GrokWebSource`, `GrokNewsSource`, -> `GrokRssSource` and `GrokXSource`, each containing granular options. +Learn more about [Remote MCP tools](https://docs.x.ai/docs/guides/tools/remote-mcp-tools). ## OpenAI diff --git a/src/Tests/GrokTests.cs b/src/Tests/GrokTests.cs index d27336f..3d5c308 100644 --- a/src/Tests/GrokTests.cs +++ b/src/Tests/GrokTests.cs @@ -251,19 +251,15 @@ public async Task GrokInvokesGrokSearchToolExcludesDomain() [SecretsFact("XAI_API_KEY")] public async Task GrokInvokesHostedCodeExecution() { - var messages = new Chat() - { - { "user", "Calculate the compound interest for $10,000 at 5% annually for 10 years" }, - }; - var grok = new GrokClient(Configuration["XAI_API_KEY"]!).AsIChatClient("grok-4-fast"); - var options = new ChatOptions - { - Tools = [new HostedCodeInterpreterTool()] - }; + var response = await grok.GetResponseAsync( + "Calculate the compound interest for $10,000 at 5% annually for 10 years", + new ChatOptions + { + Tools = [new HostedCodeInterpreterTool()] + }); - var response = await grok.GetResponseAsync(messages, options); var text = response.Text; Assert.Contains("$6,288.95", text); @@ -271,6 +267,7 @@ public async Task GrokInvokesHostedCodeExecution() .SelectMany(x => x.Contents) .OfType()); + // result content is not available by default Assert.Empty(response.Messages .SelectMany(x => x.Contents) .OfType()); @@ -293,13 +290,13 @@ public async Task GrokInvokesHostedCodeExecutionWithOutput() }; var response = await grok.GetResponseAsync(messages, options); - var text = response.Text; - Assert.Contains("$6,288.95", text); + Assert.Contains("$6,288.95", response.Text); Assert.NotEmpty(response.Messages .SelectMany(x => x.Contents) .OfType()); + // result content opted-in is found Assert.NotEmpty(response.Messages .SelectMany(x => x.Contents) .OfType());