From c9fa1fae501f54a65a6a6b98197b5ab6548a6b58 Mon Sep 17 00:00:00 2001 From: Piotr Stachaczynski Date: Thu, 23 Oct 2025 13:46:23 +0200 Subject: [PATCH] feat: include tool support --- src/assets/docs/contracts/stepbuilder.md | 180 ++++++++++++++++ src/assets/docs/contracts/toolbuilder.md | 193 ++++++++++++++++++ src/assets/docs/docs-index.json | 16 ++ .../docs/examples/example-agent-tools.md | 87 ++++++++ .../docs/examples/example-chat-tools.md | 39 ++++ 5 files changed, 515 insertions(+) create mode 100644 src/assets/docs/contracts/stepbuilder.md create mode 100644 src/assets/docs/contracts/toolbuilder.md create mode 100644 src/assets/docs/examples/example-agent-tools.md create mode 100644 src/assets/docs/examples/example-chat-tools.md diff --git a/src/assets/docs/contracts/stepbuilder.md b/src/assets/docs/contracts/stepbuilder.md new file mode 100644 index 0000000..e4a1de8 --- /dev/null +++ b/src/assets/docs/contracts/stepbuilder.md @@ -0,0 +1,180 @@ +# βš™οΈ StepBuilder Overview + +The **`StepBuilder`** class provides a fluent interface for defining the **behavioral flow of an AI Agent**. +It allows developers to specify **how an agent should process input, use memory, access knowledge, or perform role-based actions** β€” all through a clear, chainable syntax. + +This builder is primarily used when creating or configuring an Agent (e.g., via `AIHub.Agent()`), to define the ordered sequence of reasoning or operational steps the Agent should follow. + +--- + +### 🧩 Namespace + +```csharp +using MaIN.Domain.Entities.Agents.Knowledge; +using MaIN.Services.Services.Models.Commands; +``` + +--- + +### πŸ—οΈ Class Definition + +```csharp +public class StepBuilder +``` + +A utility class for constructing a list of predefined **agent execution steps**. +Each step defines a mode of operation that influences how the Agent interprets, searches, or responds to input. + +--- + +### πŸ”Ή Core Methods + +#### **`Instance`** + +```csharp +public static StepBuilder Instance => new(); +``` + +Provides a new instance of `StepBuilder` for fluent chaining. +Used as an entry point for defining a step sequence: + +```csharp +StepBuilder.Instance.Answer().Build(); +``` + +--- + +#### **`Answer()`** + +Marks a basic answering step β€” the Agent simply generates a direct response to the input. + +--- + +#### **`AnswerUseMemory()`** + +Enables the Agent to **access and use stored memory** when forming a response. + +--- + +#### **`AnswerUseKnowledge(bool alwaysSearchMemory = false)`** + +Allows the Agent to **search its knowledge base** to form an answer. +The optional `alwaysSearchMemory` flag ensures memory is always consulted alongside knowledge retrieval. + +--- + +#### **`AnswerUseKnowledgeWithTags(params string[] tags)`** + +Filters knowledge retrieval by **specific tags**, letting the Agent focus on a targeted domain of stored information. + +Example: + +```csharp +StepBuilder.Instance.AnswerUseKnowledgeWithTags("finance", "market"); +``` + +--- + +#### **`AnswerUseKnowledgeWithType(KnowledgeItemType type)`** + +Restricts knowledge usage to a particular **type** (e.g., documents, facts, summaries). + +--- + +#### **`AnswerUseKnowledgeAndMemory()`** + +Combines both **knowledge-based reasoning** and **memory recall** for more contextually rich responses. + +--- + +#### **`AnswerUseKnowledgeAndMemoryWithTags(params string[] tags)`** + +A hybrid mode using both memory and tagged knowledge retrieval. + +--- + +#### **`Become(string role)`** + +Instructs the Agent to **adopt a specific role or persona** before continuing execution. + +Example: + +```csharp +.Become("assistant_expert") +``` + +--- + +#### **`FetchData(FetchResponseType fetchResponseType = FetchResponseType.AS_Answer)`** + +Defines a step where the Agent **fetches external data**, optionally as a system-level operation. + +* `AS_Answer` β†’ Fetches data to produce a normal response +* `AS_System` β†’ Fetches data for internal processing or state updates + +--- + +#### **`Mcp()`** + +Adds an **MCP (Multi-Component Process)** step β€” typically used for complex, multi-agent or multi-step coordination workflows. + +--- + +#### **`Redirect(string agentId, string output = "AS_Output", string mode = "REPLACE")`** + +Redirects execution flow to another Agent. +Useful for **delegation or agent chaining**. + +Example: + +```csharp +.Redirect("knowledge_agent", "AS_Output", "MERGE"); +``` + +--- + +#### **`Build()`** + +Finalizes and returns the constructed list of steps. +This list is then passed to the Agent configuration pipeline. + +Example: + +```csharp +.WithSteps(StepBuilder.Instance + .AnswerUseKnowledgeAndMemory() + .Build()) +``` + +--- + +### 🧠 Example Usage + +```csharp +var steps = StepBuilder.Instance + .AnswerUseKnowledgeAndMemoryWithTags("research", "analysis") + .Become("data_researcher") + .Build(); + +await AIHub.Agent() + .WithModel("claude-sonnet-4-5-20250929") + .WithSteps(steps) + .CreateAsync(interactiveResponse: true); +``` + +--- + +### πŸ” Summary + +| Category | Purpose | +| ---------------------- | --------------------------------------------- | +| **Answer** | Simple or knowledge/memory-enhanced responses | +| **Knowledge & Memory** | Access stored or learned context | +| **Role / Behavior** | Define how the agent behaves or identifies | +| **Data Fetching** | Integrate external or internal data sources | +| **Redirection** | Delegate tasks between agents | +| **MCP** | MCP server call | + +--- + +The `StepBuilder` provides a **modular, declarative way to control agent logic**, making agent configurations expressive, reusable, and easy to reason about. diff --git a/src/assets/docs/contracts/toolbuilder.md b/src/assets/docs/contracts/toolbuilder.md new file mode 100644 index 0000000..9f38877 --- /dev/null +++ b/src/assets/docs/contracts/toolbuilder.md @@ -0,0 +1,193 @@ +# 🧰 ToolsConfigurationBuilder Overview + +The **`ToolsConfigurationBuilder`** class provides a structured and extensible way to define and register **tools** that can be used by AI agents during execution. +Tools act as **callable functions** β€” external operations the model can invoke dynamically to retrieve data, perform computations, or trigger actions. + +This builder simplifies tool creation by offering multiple overloads for different execution patterns (sync/async, typed/untyped, parameterized/no-parameter tools). + +--- + +### 🧩 Namespace + +```csharp +using System.Text.Json; +using MaIN.Domain.Entities.Tools; +``` + +--- + +### πŸ—οΈ Class Definition + +```csharp +public class ToolsConfigurationBuilder +``` + +A fluent builder for constructing a **`ToolsConfiguration`** object, which contains a list of **`ToolDefinition`** entries and optional configuration settings (such as tool selection behavior). + +Each added tool defines a function name, description, expected parameters, and an execution delegate. + +--- + +### πŸ”Ή Core Usage + +Used during agent configuration to specify tools the model can access: + +```csharp +.WithTools(new ToolsConfigurationBuilder() + .AddTool( + name: "get_weather", + description: "Retrieve current weather information", + parameters: new { type = "object", properties = new { city = new { type = "string" } } }, + execute: WeatherTools.GetWeather) + .WithToolChoice("auto") + .Build()) +``` + +--- + +### πŸ”§ Methods Overview + +#### **`AddDefaultTool(string type)`** + +Registers a basic tool definition with a specific type. +Used when predefined tool behavior is already encapsulated elsewhere. + +```csharp +.AddDefaultTool("system_logger") +``` + +--- + +#### **`AddTool(string name, string description, object parameters, Func> execute)`** + +Registers an asynchronous tool that receives raw JSON input and returns a serialized string result. +This version is suitable when working directly with serialized arguments. + +--- + +#### **`AddTool(string name, string description, object parameters, Func execute)`** + +Registers a synchronous version of the above method. +The provided function executes immediately and returns a plain string result. + +--- + +#### **`AddTool(string name, string description, object parameters, Func> execute)`** + +Registers a **typed asynchronous tool**. +The input JSON is automatically deserialized into a strongly-typed object (`TArgs`), and the result is serialized back to JSON. + +Example: + +```csharp +.AddTool( + "create_note", + "Create a new note with a title and content", + new + { + type = "object", + properties = new + { + title = new { type = "string", description = "Title of the note" }, + content = new { type = "string", description = "Content of the note" } + }, + required = new[] { "title", "content" } + }, + NoteTools.CreateNoteAsync) +``` + +--- + +#### **`AddTool(string name, string description, object parameters, Func execute)`** + +Registers a **typed synchronous tool**, similar to the previous method but without asynchronous execution. + +The input is deserialized into the specified argument type (`TArgs`), the tool executes synchronously, and the result is serialized to JSON. + +--- + +#### **`AddTool(string name, string description, Func> execute)`** + +Registers an **asynchronous parameterless tool**, ideal for actions that don’t require inputs (e.g., fetching current time or status). + +Example: + +```csharp +.AddTool("get_current_time", "Get the current date and time", Tools.GetCurrentTimeAsync) +``` + +--- + +#### **`AddTool(string name, string description, Func execute)`** + +Registers a **synchronous parameterless tool**. +This overload is ideal for lightweight, immediate-return tools. + +--- + +#### **`WithToolChoice(string choice)`** + +Specifies the **tool selection strategy** for the agent. +Common values: + +* `"auto"` β†’ The model decides when to use tools automatically. +* `"none"` β†’ Disables tool invocation. +* `"required"` β†’ Forces tool usage if applicable. + +--- + +#### **`Build()`** + +Finalizes the configuration and returns a fully constructed **`ToolsConfiguration`** object. + +--- + +### 🧠 Example Usage + +```csharp +var toolsConfig = new ToolsConfigurationBuilder() + .AddTool( + name: "get_weather", + description: "Get current weather conditions for a city", + parameters: new + { + type = "object", + properties = new + { + city = new { type = "string", description = "City name" } + }, + required = new[] { "city" } + }, + execute: WeatherTools.GetWeatherAsync) + .AddTool( + name: "get_current_time", + description: "Return the current local time", + execute: Tools.GetCurrentTime) + .WithToolChoice("auto") + .Build(); +``` + +This configuration can then be attached to a chat or agent: + +```csharp +await AIHub.Chat() + .WithModel("gpt-5-nano") + .WithTools(toolsConfig) + .CompleteAsync(interactive: true); +``` + +--- + +### πŸ“˜ Summary + +| Category | Description | +| ----------------- | -------------------------------------------------------------------------------------- | +| **Purpose** | Defines callable tools the model can execute during interaction | +| **Supports** | Synchronous & asynchronous tools, typed & untyped execution | +| **Serialization** | Automatically handles JSON deserialization for input and serialization for output | +| **Integration** | Used directly with agents or chat sessions via `.WithTools()` | +| **Flexibility** | Allows parameterized tools, parameterless tools, and dynamic tool selection strategies | + +--- + +The `ToolsConfigurationBuilder` provides a **clean, declarative, and extensible interface** for integrating external logic into AI-driven workflows, enabling agents to **go beyond text generation** and interact with real-world data and actions seamlessly. diff --git a/src/assets/docs/docs-index.json b/src/assets/docs/docs-index.json index 5b4c855..098235b 100644 --- a/src/assets/docs/docs-index.json +++ b/src/assets/docs/docs-index.json @@ -54,6 +54,10 @@ "title":"Chat with reasoning", "path":"examples/example-chat-reasoning" }, + { + "title":"Chat with tools (simple)", + "path":"examples/example-chat-tools" + }, { "title":"Chat with files", "path":"examples/example-chat-files" @@ -91,6 +95,10 @@ "title":"Multi Backend Agent", "path":"examples/multi-backend-agent-redirect" }, + { + "title":"Agent Tools (advanced))", + "path":"examples/example-agent-tools" + }, { "title":"Agent data source", "path":"examples/example-agent-source" @@ -237,6 +245,14 @@ "title":"FlowContext", "path":"contracts/flow-context" }, + { + "title":"StepBuilder", + "path":"contracts/stepbuilder" + }, + { + "title":"ToolBuilder", + "path":"contracts/toolbuilder" + }, { "title":"Extensions", "path":"contracts/extensions" diff --git a/src/assets/docs/examples/example-agent-tools.md b/src/assets/docs/examples/example-agent-tools.md new file mode 100644 index 0000000..dfec344 --- /dev/null +++ b/src/assets/docs/examples/example-agent-tools.md @@ -0,0 +1,87 @@ +# 🧠 Anthropic Tool Example + +The **AnthropicToolExample** demonstrates how to integrate **Anthropic’s Claude** model with **tool usage**, enabling the model to interact with external functions such as listing, reading, and saving notes. + +### πŸ“ Code Example + +```csharp +public async Task Start() +{ + AnthropicExample.Setup(); + Console.WriteLine("(Anthropic) Tool example is running!"); + + var context = await AIHub.Agent() + .WithModel("claude-sonnet-4-5-20250929") + .WithSteps(StepBuilder.Instance + .Answer() + .Build()) + .WithTools(new ToolsConfigurationBuilder() + .AddTool( + "list_notes", + "List all available notes", + new + { + type = "object", + properties = new + { + folder = new { type = "string", description = "Notes folder", @default = "notes" } + } + }, + NoteTools.ListNotes) + .AddTool( + "read_note", + "Read the content of a specific note", + new + { + type = "object", + properties = new + { + noteName = new + { type = "string", description = "Name of the note (without .txt extension)" } + }, + required = new[] { "noteName" } + }, + NoteTools.ReadNote) + .AddTool( + "save_note", + "Save or update a note with new content", + new + { + type = "object", + properties = new + { + noteName = new + { type = "string", description = "Name of the note (without .txt extension)" }, + content = new { type = "string", description = "Content to save in the note" } + }, + required = new[] { "noteName", "content" } + }, + NoteTools.SaveNote) + .WithToolChoice("auto") + .Build()) + .CreateAsync(interactiveResponse: true); + + await context.ProcessAsync("What notes do I currently have?"); + + Console.WriteLine("--//--"); + + await context.ProcessAsync("Create a new note for a shopping list that includes healthy foods."); +} +``` + +## πŸ”Ή How It Works + +1. **Initialize Anthropic API** β†’ `AnthropicExample.Setup()` configures access to the Anthropic API. +2. **Create an AI agent** β†’ `AIHub.Agent()` initializes a Claude-powered agent instance. +3. **Select a model** β†’ `.WithModel("claude-sonnet-4-5-20250929")` specifies the Claude model version to use. +4. **Define reasoning steps** β†’ `.WithSteps(StepBuilder.Instance.Answer().Build())` sets up how the agent processes input. +5. **Add tools** β†’ `.WithTools(...)` registers functions that the model can call: + + * **`list_notes`** β†’ Lists available notes in a folder. + * **`read_note`** β†’ Reads the content of a specified note. + * **`save_note`** β†’ Creates or updates a note with new content. +6. **Automatic tool selection** β†’ `.WithToolChoice("auto")` allows Claude to decide when to use a tool. +7. **Enable interactive responses** β†’ `.CreateAsync(interactiveResponse: true)` starts the agent with live, tool-enabled interaction. +8. **Process user inputs** β†’ `context.ProcessAsync()` handles queries and executes tool actions when appropriate. + +This example demonstrates how **Claude can combine natural language understanding with structured tool use**, enabling intelligent, context-aware operations such as managing and updating note data through simple conversational commands. diff --git a/src/assets/docs/examples/example-chat-tools.md b/src/assets/docs/examples/example-chat-tools.md new file mode 100644 index 0000000..1394077 --- /dev/null +++ b/src/assets/docs/examples/example-chat-tools.md @@ -0,0 +1,39 @@ +# πŸ’¬ OpenAI Chat Example with Tools + +The **OpenAIChatWithToolsExample** showcases how to integrate OpenAI’s GPT-5 model with *tool calling* capabilities β€” allowing the model to access and execute custom tools for enhanced functionality. + +### πŸ“ Code Example + +```csharp +public async Task Start() +{ + OpenAiExample.Setup(); // We need to provide OpenAI API key + + Console.WriteLine("(OpenAi) ChatExample with tools is running!"); + + await AIHub.Chat() + .WithModel("gpt-5-nano") + .WithMessage("What time is it right now?") + .WithTools(new ToolsConfigurationBuilder() + .AddTool( + name: "get_current_time", + description: "Get the current date and time", + execute: Tools.GetCurrentTime) + .WithToolChoice("auto") + .Build()) + .CompleteAsync(interactive: true); +} +``` + +## πŸ”Ή How It Works + +1. **Set up OpenAI API** β†’ `OpenAiExample.Setup()` (requires your API key) +2. **Start a chat session** β†’ `AIHub.Chat()` +3. **Select a model** β†’ `.WithModel("gpt-5-nano")` +4. **Send a message** β†’ `.WithMessage("What time is it right now?")` +5. **Configure tools** β†’ `.WithTools(...)` adds custom tool definitions the model can use + + * Here, the `get_current_time` tool allows GPT-5 to retrieve the current system time. +6. **Execute interactively** β†’ `.CompleteAsync(interactive: true)` runs the chat with real-time interaction. + +This example demonstrates how easy it is to empower GPT-5 with **external tool integration**, enabling the model to **perform real actions**β€”such as fetching live dataβ€”beyond text generation. With minimal setup, developers can build dynamic, intelligent systems that blend AI reasoning with practical functionality.