Executing query until there is nothing more left
Sorry, but you definitely need a null check here:


  if (result.Any())


Else there is not much to comment.

About the usage:

I don't understand, why you create a lambda for the query argument:


 async Task Main()
{
    var numbers = new NumberRepository();
    await Unfold.ForEachAsync
    (
        query: async token =&gt; await numbers.GetNumbersAsync(token), 
        body: ProcessBatch, 
        CancellationToken.None
    );
}



Why not just:

async Task Main()
{
  var numbers = new NumberRepository();
  await Unfold.ForEachAsync
  (
      query: numbers.GetNumbersAsync,
      body: ProcessBatch,
      CancellationToken.None
  );
}


numbers.GetNumbersAsync is awaitable already?