The Messages API: request, response, history

The model is stateless. Your app keeps the conversation, resends it on every call, and checks why the reply stopped.

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

The idea

A chat with a model is a series of independent requests. Each request carries a system prompt (the assistant’s role and rules), the list of messages so far with roles user and assistant, and a maximum reply length. The response carries the new text and a stop reason. The service remembers nothing between calls, so your app owns the history: it adds each turn and sends the whole list again next time.

Code

public sealed record Message(string Role, string Text);
public sealed record MessagesRequest(string System, IReadOnlyList<Message> Messages, int MaxTokens);

public sealed class ChatSession(IMessagesClient client)
{
    private readonly string _system = "You are a concise tutor for beginners.";
    private readonly List<Message> _history = new();

    public async Task<string> AskAsync(string userText)
    {
        _history.Add(new Message("user", userText));
        var request = new MessagesRequest(_system, _history, MaxTokens: 200);
        var reply = await client.SendAsync(request);
        if (reply.StopReason == "max_tokens")
            Console.WriteLine("Cut off: raise MaxTokens or ask to continue.");
        _history.Add(new Message("assistant", reply.Text));
        return reply.Text;
    }
}

Tips

In the .NET library

Register a typed client class with IHttpClientFactory, and keep the API key in configuration or a secret store, never in source code. Keep one ChatSession per conversation (per user), not a shared singleton, so people’s histories never mix.