Compartilhar via


Criando um agente

Importante

Em janeiro de 2026, o projeto AI Shell não está mais sendo mantido ativamente. Este projeto deve ser considerado arquivado do ponto de vista da engenharia.

Um agente é uma biblioteca de códigos que faz interface com o Shell de IA para falar com um modelo de linguagem grande específico ou outro provedor de assistência. Os usuários conversam com os agentes usando linguagem natural para obter a saída ou assistência desejada. Os agentes são implementados como classes C# que implementam a interface ILLMAgent do pacote de AIShell.Abstraction.

Para obter detalhes sobre a camada de e , consulte a documentação da arquitetura do AI Shell .

Este artigo é um guia passo a passo para criar um agente para o modelo de linguagem Ollama . O objetivo deste artigo é fornecer um exemplo simples de como criar um agente. Há uma implementação mais robusta do agente Ollama AIShell.Ollama.Agent na pasta do repositório.

Pré-requisitos

  • SDK do .NET 8 ou mais recente
  • PowerShell 7.4.6 ou mais recente

Etapas para criar um agente

Para este exemplo, criamos um agente para se comunicar com o modelo phi3 de linguagem usando Ollama. Ollama é uma ferramenta CLI para gerenciar e usar LLM/SLMs criados localmente.

Etapa 1: Criar um novo projeto

O primeiro passo é criar um novo projeto classlib .

  1. Criar uma nova pasta chamada OllamaAgent

  2. Execute o seguinte comando para criar um novo projeto:

    dotnet new classlib
    

Etapa 2: Adicionar os pacotes necessários

No projeto recém-criado, você precisa instalar o pacote AIShell.Abstraction da galeria do NuGet. Instale o pacote NuGet usando o seguinte comando:

dotnet add package AIShell.Abstraction --version 1.0.0-preview.2

Esse comando adiciona o pacote ao arquivo .csproj. O arquivo .csproj deve conter o seguinte XML:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <SuppressNETCoreSdkPreviewMessage>true</SuppressNETCoreSdkPreviewMessage>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="AIShell.Abstraction" Version="1.0.0-preview.2" />
  </ItemGroup>
</Project>

Importante

Verifique se você está na versão mais recente da galeria do NuGet.

Etapa 3: Implementar a classe de agente

Para implementar a interface ILLMAgent, modifique o arquivo Class1.cs.

  1. Renomear o arquivo para OllamaAgent.cs
  2. Renomeie a classe para OllamaAgent
  3. Adicionar os namespaces do .NET que são usados pelo código na implementação
using System.Diagnostics;
using System.Text;
using System.Text.Json;
using AIShell.Abstraction;

namespace AIShell.Ollama.Agent;

public sealed class OllamaAgent : ILLMAgent
{

}

Etapa 4: Adicionar membros e métodos de classe necessários

Em seguida, implemente as variáveis e métodos necessários da classe de agente. Os comentários fornecem descrições dos membros da classe OllamaAgent. O _chatService membro é uma instância da classe OllamaChatService , que você implementa em uma etapa posterior.

public sealed class OllamaAgent : ILLMAgent
{
    /// <summary>
    /// The name of the agent
    /// </summary>
    public string Name => "ollama";

    /// <summary>
    /// The description of the agent to be shown at start up
    /// </summary>
    public string Description => "This is an AI assistant that uses the Ollama CLI tool. Be sure to follow all prerequisites in https://aka.ms/ollama/readme";

    /// <summary>
    /// This is the company added to `/like` and `/dislike` verbiage for who the telemetry helps.
    /// </summary>
    public string Company => "Microsoft";

    /// <summary>
    /// These are samples that are shown at start up for good questions to ask the agent
    /// </summary>
    public List<string> SampleQueries => [
        "How do I list files in a given directory?"
    ];

    /// <summary>
    /// These are any optional legal/additional information links you want to provide at start up
    /// </summary>
    public Dictionary<string, string> LegalLinks { private set; get; }

    /// <summary>
    /// This is the chat service to call the API from
    /// </summary>
    private OllamaChatService _chatService;

    /// <summary>
    /// A string builder to render the text at the end
    /// </summary>
    private StringBuilder _text;

    /// <summary>
    /// Dispose method to clean up the unmanaged resource of the chatService
    /// </summary>
    public void Dispose()
    {
        _chatService?.Dispose();
    }

    /// <summary>
    /// Initializing function for the class when the shell registers an agent
    /// </summary>
    /// <param name="config">Agent configuration for any configuration file and other settings</param>
    public void Initialize(AgentConfig config)
    {
        _text = new StringBuilder();
        _chatService = new OllamaChatService();

        LegalLinks = new(StringComparer.OrdinalIgnoreCase)
        {
            ["Ollama Docs"] = "https://github.com/ollama/ollama",
            ["Prerequisites"] = "https://aka.ms/ollama/readme"
        };

    }

    /// <summary>
    /// Get commands that an agent can register to the shell when being loaded
    /// </summary>
    public IEnumerable<CommandBase> GetCommands() => null;

    /// <summary>
    /// Gets the path to the setting file of the agent.
    /// </summary>
    public string SettingFile { private set; get; } = null;

    /// <summary>
    /// Refresh the current chat by starting a new chat session.
    /// An agent can reset chat states in this method.
    /// </summary>
    public void RefreshChat() {}

    /// <summary>
    /// Gets a value indicating whether the agent accepts a specific user action feedback.
    /// </summary>
    /// <param name="action">The user action.</param>
    public bool CanAcceptFeedback(UserAction action) => false;

    /// <summary>
    /// A user action was taken against the last response from this agent.
    /// </summary>
    /// <param name="action">Type of the action.</param>
    /// <param name="actionPayload"></param>
    public void OnUserAction(UserActionPayload actionPayload) {}

    /// <summary>
    /// Main chat function that takes
    /// </summary>
    /// <param name="input">The user input from the chat experience</param>
    /// <param name="shell">The shell that provides host functionality</param>
    /// <returns>Task Boolean that indicates whether the query was served by the agent.</returns>
    public async Task<bool> Chat(string input, IShell shell)
    {

    }
}

Para a implementação inicial, o agente retorna "Hello World!", provando que você criou as interfaces corretas. Você também precisa adicionar um try-catch bloco para capturar e lidar com quaisquer exceções quando o usuário tentar cancelar a operação.

Adicione o código a seguir ao método Chat.

public async Task<bool> Chat(string input, IShell shell)
{
    // Get the shell host
    IHost host = shell.Host;

    // get the cancellation token
    CancellationToken token = shell.CancellationToken;

    try
    {
       host.RenderFullResponse("Hello World!");
    }
    catch (OperationCanceledException e)
    {
        _text.AppendLine(e.ToString());

        host.RenderFullResponse(_text.ToString());

        return false;
    }

    return true;
}

Etapa 5: Adicionar verificação de Ollama

Em seguida, você precisa ter certeza de que o Ollama está em execução.

public async Task<bool> Chat(string input, IShell shell)
{
    // Get the shell host
    IHost host = shell.Host;

    // get the cancellation token
    CancellationToken token = shell.CancellationToken;

    if (Process.GetProcessesByName("ollama").Length is 0)
    {
        host.RenderFullResponse("Please be sure that Ollama is installed and the server is running. Ensure that you have met all the prerequisites in the README for this agent.");
        return false;
    }

    // Calls to the API will go here

    return true;
}

Etapa 6: Criar estruturas de dados para trocar dados com o Serviço de Chat

Antes de usar a API do Ollama, você precisa criar classes que enviam entradas e recebem respostas da API do Ollama. O exemplo de Ollama a seguir mostra o formato da entrada e a resposta do agente.

Este exemplo chama a API Ollama com streaming desabilitado. O Ollama gera uma única resposta fixa. No futuro, você poderá adicionar recursos de streaming para que as respostas possam ser renderizadas em tempo real, conforme o agente as recebe.

Para definir as estruturas de dados, crie um novo arquivo na mesma pasta chamada OllamaSchema.cs. Copie o código a seguir para o arquivo.

namespace AIShell.Ollama.Agent;

// Query class for the data to send to the endpoint
internal class Query
{
    public string prompt { get; set; }
    public string model { get; set; }

    public bool stream { get; set; }
}

// Response data schema
internal class ResponseData
{
    public string model { get; set; }
    public string created_at { get; set; }
    public string response { get; set; }
    public bool done { get; set; }
    public string done_reason { get; set; }
    public int[] context { get; set; }
    public double total_duration { get; set; }
    public long load_duration { get; set; }
    public int prompt_eval_count { get; set; }
    public int prompt_eval_duration { get; set; }
    public int eval_count { get; set; }
    public long eval_duration { get; set; }
}

internal class OllamaResponse
{
    public int Status { get; set; }
    public string Error { get; set; }
    public string Api_version { get; set; }
    public ResponseData Data { get; set; }
}

Agora você tem as peças necessárias para construir um serviço de chat que usa a API Ollama. Uma classe de serviço de chat separada não é necessária, mas é útil abstrair as chamadas para a API.

Crie um novo arquivo chamado OllamaChatService.cs na mesma pasta que o agente. Copie o código de exemplo para o arquivo.

Dica

Este exemplo usa um ponto de extremidade codificado e um modelo de linguagem para a API Ollama. No futuro, você poderá definir parâmetros configuráveis em um arquivo de configuração do agente.

using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;

using AIShell.Abstraction;

namespace AIShell.Ollama.Agent;

internal class OllamaChatService : IDisposable
{
    /// <summary>
    /// Ollama endpoint to call to generate a response
    /// </summary>
    internal const string Endpoint = "http://localhost:11434/api/generate";

    /// <summary>
    /// Http client
    /// </summary>
    private readonly HttpClient _client;

    /// <summary>
    /// Initialization method to initialize the http client
    /// </summary>

    internal OllamaChatService()
    {
        _client = new HttpClient();
    }

    /// <summary>
    /// Dispose of the http client
    /// </summary>
    public void Dispose()
    {
        _client.Dispose();
    }

    /// <summary>
    /// Preparing chat with data to be sent
    /// </summary>
    /// <param name="input">The user input from the chat experience</param>
    /// <returns>The HTTP request message</returns>
    private HttpRequestMessage PrepareForChat(string input)
    {
        // Main data to send to the endpoint
        var requestData = new Query
        {
            model = "phi3",
            prompt = input,
            stream = false
        };

        var json = JsonSerializer.Serialize(requestData);

        var data = new StringContent(json, Encoding.UTF8, "application/json");
        var request = new HttpRequestMessage(HttpMethod.Post, Endpoint) { Content = data };

        return request;
    }

    /// <summary>
    /// Getting the chat response async
    /// </summary>
    /// <param name="context">Interface for the status context used when displaying a spinner.</param>
    /// <param name="input">The user input from the chat experience</param>
    /// <param name="cancellationToken">The cancellation token to exit out of request</param>
    /// <returns>Response data from the API call</returns>
    internal async Task<ResponseData> GetChatResponseAsync(IStatusContext context, string input, CancellationToken cancellationToken)
    {
        try
        {
            HttpRequestMessage request = PrepareForChat(input);
            HttpResponseMessage response = await _client.SendAsync(request, cancellationToken);
            response.EnsureSuccessStatusCode();

            context?.Status("Receiving Payload ...");
            Console.Write(response.Content);
            var content = await response.Content.ReadAsStreamAsync(cancellationToken);
            return JsonSerializer.Deserialize<ResponseData>(content);
        }
        catch (OperationCanceledException)
        {
            // Operation was cancelled by user.
        }

        return null;
    }
}

Etapa 7: Chamar o serviço de chat

Em seguida, você precisa chamar o serviço de chat na classe de agente principal. Modifique o método Chat() para chamar o serviço de chat e renderizar a resposta ao usuário. O exemplo a seguir mostra o método de Chat() concluído.

public async Task<bool> Chat(string input, IShell shell)
{
    // Get the shell host
    IHost host = shell.Host;

    // get the cancellation token
    CancellationToken token = shell.CancellationToken;

    if (Process.GetProcessesByName("ollama").Length is 0)
    {
        host.RenderFullResponse("Please be sure that Ollama is installed and the server is running. Ensure that you have met all the prerequisites in the README for this agent.");
        return false;
    }

    ResponseData ollamaResponse = await host.RunWithSpinnerAsync(
        status: "Thinking ...",
        func: async context => await _chatService.GetChatResponseAsync(context, input, token)
    ).ConfigureAwait(false);

    if (ollamaResponse is not null)
    {
        // render the content
        host.RenderFullResponse(ollamaResponse.response);
    }

    return true;
}

O código do agente está concluído.

Etapa 8: Criar e testar o agente

Em seguida, você precisa compilar e testar se o código está funcionando conforme o esperado. Execute o seguinte comando:

dotnet build

Esse comando cria todos os pacotes necessários na pasta \bin\Debug\net8.0 do projeto.

Para que aish carregue o agente, você precisa copiar os arquivos .dll para uma pasta na pasta Agents. O nome da pasta deve ser o mesmo que o nome do agente.

Você pode instalar agentes em um dos dois locais:

  • Na pasta Agents no local onde você instalou aish.exe. O [script de instalação][08] para instalações do Shell de IA no %LOCALAPPDATA%\Programs\AIShell. Crie a pasta %LOCALAPPDATA%\Programs\AIShell\Agents\OllamaAgent.
  • Como alternativa, você instala agentes no %USERPROFILE%\.aish\Agents. Crie a pasta %USERPROFILE%\.aish\Agents\OllamaAgent.

Copie os arquivos de .dll para a pasta do agente que você criou. Você deverá ver o agente quando iniciar aish.

AI Shell
v1.0.0-preview.2

Please select an agent to use:

    azure
   >ollama
    openai-gpt

Como posso compartilhar meu próprio agente?

Não há como compartilhar seus agentes em um repositório centralizado. Sugerimos bifurcar este repositório para desenvolvimento de seu próprio agente. Você pode compartilhar um link da bifurcação na seção da guia discussões deste repositório. Para usar um agente, coloque os arquivos do dll agente agents na pasta do diretório base do aish.exe. O AI Shell carrega automaticamente os agentes dessa pasta.