Tool use: the model asks, your app acts

The model never runs anything. It asks for a tool call, your code validates and runs it, and returns the result.

Time O(t)Space O(n)Code C#
Watch it animatedStep through it, with the running line highlighted. Free with an account.

The idea

Tool use lets a model work with the real world without ever touching it. You describe the tools (name, purpose, input shape). When the model decides one is needed, it replies with a tool_use block and stops with the reason tool_use. Your app checks the request, runs the real function, and sends the output back as a tool_result. Then the model continues and writes the final answer. The model proposes; your code disposes.

Code

public record ToolDef(string Name, string Description);

public static class OrderBot
{
    private static readonly ToolDef[] Tools = { new("get_order_status", "Look up an order by its id") };

    public static async Task<string> AnswerAsync(IMessagesClient client, string question)
    {
        var messages = new List<Message> { Message.User(question) };
        while (true)
        {
            var reply = await client.SendAsync(messages, Tools);
            messages.Add(reply.AsMessage());
            if (reply.StopReason != "tool_use") return reply.Text;

            foreach (var use in reply.ToolUses)
            {
                string result;
                if (!IsValid(use)) result = "error: invalid input";
                else result = await RunToolAsync(use.Name, use.Input);
                messages.Add(Message.ToolResult(use.Id, result));
            }
        }
    }
}

Tips

In the .NET library

Represent each tool as a normal C# method plus a JSON schema for its input. Use System.Text.Json to deserialize use.Input into a typed record, which doubles as validation. Return clear error strings so the model can recover or explain.