> For the complete documentation index, see [llms.txt](https://docs.skail.dev/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.skail.dev/construir/sdk-.net/skailfunction.md).

# \[SkailFunction]

Marca um método como orquestrador durável. O método vira um ponto de entrada de execução: o skail inicia, retoma e acompanha o fluxo a partir dele. Esta é a referência do atributo; o conceito está em [Modelo de programação](/aprender/fundamentos/modelo-de-programacao.md).

## Assinatura

```csharp
// Formas do atributo (use uma por método):
// [SkailFunction]
// [SkailFunction(retryCount: 3)]
// [SkailFunction(skailMethodName: "EmitirFaturaV2")]
// [SkailFunction(skailMethodName: "EmitirFaturaV2", retryCount: 5)]
[SkailFunction]
public async SkailTask NomeDoMetodo(/* argumentos */)   // ou SkailTask<T>
```

| Parâmetro         | Tipo      | Default | Descrição                                                                                             |
| ----------------- | --------- | ------- | ----------------------------------------------------------------------------------------------------- |
| `skailMethodName` | `string?` | `null`  | Endereço explícito da function. Ver regras de URI abaixo.                                             |
| `retryCount`      | `uint`    | `15`    | Máximo de reentregas da execução quando a function lança exceção. Commands já concluídos não repetem. |

## Regras do método

| Regra                                 | Detalhe                                                                                                                                    | Quem cobra                                            |
| ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------- |
| Método de instância                   | Nunca `static`. A classe é registrada no DI automaticamente                                                                                | Analyzer (SKAIL001)                                   |
| `async`                               | Sempre                                                                                                                                     | Analyzer (SKAIL002)                                   |
| Retorno `SkailTask` ou `SkailTask<T>` | Nunca `Task`/`Task<T>`                                                                                                                     | Analyzer (SKAIL001)                                   |
| `public`                              | Sempre `public`                                                                                                                            | Analyzer (SKAIL001)                                   |
| Argumentos e retorno serializáveis    | `System.Text.Json`: primitivos, `Guid`, `DateTime`, records, DTOs, coleções. Nunca `SkailTask`                                             | Runtime, ao registrar o passo                         |
| Corpo determinístico                  | Sem I/O, relógio, aleatoriedade, `Task.Delay`, `Task.WhenAll`. Ver [Determinismo e replay](/aprender/fundamentos/determinismo-e-replay.md) | Runtime, no replay (`SkailNonDeterministicException`) |

## Comportamento

O corpo é reexecutado a cada retomada (início, fim de delay, evento recebido, falha, restart). A cada `await`, o runtime devolve o resultado daquela vez se o passo já foi concluído, ou executa e registra o passo. Pode chamar `[SkailCommand]`, outras `[SkailFunction]` (que viram orquestrações filhas com o próprio histórico) e as primitivas `SkailTask.*`. Uma function é iniciada pelo trigger ou chamada por outra function, nunca por um command.

Quando o corpo lança exceção (inclusive uma vinda de command que esgotou o próprio `retryCount`), a execução é reentregue até `retryCount` vezes; ao esgotar, fica como falha no Monitor e pode ser retomada manualmente. Ver [Falhas, retries e idempotência](/aprender/fundamentos/falhas-retries-e-idempotencia.md).

## Endereço (URI) e skailMethodName

Toda function tem um endereço no formato `imagem:versao/metodo`, onde `imagem:versao` é o workload (`SKAIL_WORKLOAD`). É esse endereço que o trigger usa (`/trigger/{imagem}/{versao}/{metodo}/{id}`) e ao qual as execuções em andamento continuam endereçadas.

| `skailMethodName`                                        | Endereço resultante                       |
| -------------------------------------------------------- | ----------------------------------------- |
| omitido                                                  | `{workload atual}/{NomeDoMetodo}`         |
| `"EmitirFaturaV2"` (só nome)                             | `{workload atual}/EmitirFaturaV2`         |
| `"faturamento:v2.0.0/EmitirFatura"` com imagem igual     | `{workload atual}/EmitirFatura`           |
| `"faturamento:v2.0.0/EmitirFatura"` com imagem diferente | literal `faturamento:v2.0.0/EmitirFatura` |

O uso principal é versionar: manter a function antiga com o nome antigo e publicar a nova com outro `skailMethodName`, enquanto execuções em andamento terminam. Para isso, use um nome novo (`"EmitirFaturaV2"`): o endereço passa a ser `{workload atual}/EmitirFaturaV2`, diferente do endereço da function antiga. Um `skailMethodName` no formato `imagem:versao/metodo` com a mesma imagem do workload atual não versiona pela versão: ele resolve para `{workload atual}/metodo` e a versão escrita no atributo é ignorada. Ver [Versionamento](/aprender/fundamentos/versionamento-de-codigo-com-execucoes-em-andamento.md). Prefira um nome só com letras e números.

## Exemplo

```csharp
using Skail.Platform.Runtime.Standard;
using Skail.Platform.Runtime.Standard.Threading;

public class Faturamento
{
    private readonly IGatewayPagamento _gateway;
    public Faturamento(IGatewayPagamento gateway) => _gateway = gateway;

    [SkailFunction(retryCount: 10)]
    public async SkailTask<bool> EmitirFatura(Guid faturaId, decimal valor)
    {
        var resultado = await CobrarCartao(faturaId, valor);
        if (resultado != ResultadoCobranca.Aprovado) return false;

        await SkailTask.Delay(TimeSpan.FromDays(1));
        await EmitirNota(faturaId);
        return true;
    }

    [SkailCommand]
    public async SkailTask<ResultadoCobranca> CobrarCartao(Guid faturaId, decimal valor)
        => await _gateway.Cobrar(faturaId, valor); // faturaId como chave de idempotência

    [SkailCommand]
    public async SkailTask EmitirNota(Guid faturaId) { /* ... */ }
}
```

## Observabilidade

Cada execução aparece no Monitor com TaskId, estado, linha do tempo dos passos, retentativas e erros; cada function abre um span de rastreamento sob o `traceparent` do trigger. Functions filhas aparecem correlacionadas à pai.

## Erros relacionados

| Erro                              | Causa                                                                                                  |
| --------------------------------- | ------------------------------------------------------------------------------------------------------ |
| SKAIL001 / SKAIL002 na compilação | Assinatura fora das regras                                                                             |
| `SkailNonDeterministicException`  | Corpo não determinístico ou fluxo alterado com execuções em andamento                                  |
| "Target method not found"         | Endereço da execução não corresponde a nenhuma function publicada: `SKAIL_WORKLOAD` ou nome diferentes |
| "StateMachine not registered."    | Método não descoberto: assembly sem `[assembly: VisibleToSkailPlatform]`, método não `async`           |

## Veja também

[SkailCommand](/construir/sdk-.net/skailcommand.md), [SkailTask e SkailTask\<T>](/construir/sdk-.net/skailtask-e-skailtask-less-than-t-greater-than.md), [Regras do analyzer](/construir/sdk-.net/regras-do-analyzer-skail001-skail002-skail003.md), [POST /trigger](/construir/api-http/post-trigger-workload-versao-funcao-id.md).
