> 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/referencia/sdk-typescript-e-outras-linguagens.md).

# SDKs e linguagens

Os fluxos do skail são escritos com o SDK da sua linguagem: hoje C# (.NET) e TypeScript, com Java, Python e outras linguagens a caminho.

Quem inicia um fluxo ou dispara um evento pode estar em qualquer linguagem, pela API HTTP.

## Hoje

O SDK é o pacote que permite escrever functions e commands duráveis. O modelo é o mesmo em todas as linguagens:

* uma function orquestra o fluxo;
* cada operação de I/O fica em um command com retry e resultado gravado;
* as esperas por tempo e por evento externo são duráveis.

Os exemplos desta documentação, inclusive o [Quickstart](/comece-aqui/quickstart.md), aparecem em abas, uma por linguagem.

| Linguagem  | Pacotes                                                                                                                                                                                                               | Requisito                      |
| ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------ |
| C#         | [`Skail.Platform.Runtime`](https://www.nuget.org/packages/Skail.Platform.Runtime/), no NuGet.org                                                                                                                      | .NET 8 ou superior             |
| TypeScript | [`@skail/runtime`](https://www.npmjs.com/package/@skail/runtime) e [`@skail/build`](https://www.npmjs.com/package/@skail/build), no npm; [`@skail/testing`](https://www.npmjs.com/package/@skail/testing) para testes | Node.js 20, 22 ou 24 em diante |

## Como rodar

Em todas as linguagens a aplicação tem classes com functions e commands e um host, que fica em execução buscando trabalho no skail, configurado pelas variáveis `SKAIL_*`. O que muda é como o runtime conhece os métodos: em C#, pelo registro no host; em TypeScript, pelo manifest que o `skail build` gera.

{% tabs %}
{% tab title="C#" %}
Uma aplicação .NET com o pacote `Skail.Platform.Runtime`. O atributo de assembly expõe as functions e os commands ao runtime, e `UseSkail()` registra o runtime no host:

{% code lineNumbers="true" %}

```csharp
// Program.cs
using Microsoft.Extensions.Hosting;
using Skail.Platform.Runtime;

[assembly: VisibleToSkailPlatform]

var builder = Host.CreateApplicationBuilder(args);
builder.UseSkail();

await builder.Build().RunAsync();
```

{% endcode %}

A referência está em [Configuração do host](/referencia/sdk-csharp/configuracao-do-host.md), e a referência completa do SDK, em [SDK C#](/referencia/sdk-csharp.md).
{% endtab %}

{% tab title="TypeScript" %}
Um entry point exporta as classes com `@SkailFunction` e `@SkailCommand` (e, se preciso, `providers`), o build gera o bundle e o manifest do workload, e o host carrega o bundle.

O entry point:

{% code lineNumbers="true" %}

```typescript
// src/entries/app.ts
export { MinhaFuncao } from "../minha-funcao.js";
```

{% endcode %}

O build, que gera o bundle e o manifest do workload:

```bash
# build: gera o bundle e o manifest do workload
node_modules/.bin/skail build src/entries/app.ts --workload meu-workload:1.0.0 \
  --out .skail/app/skail-functions.mjs --manifest .skail/app/manifest.json
```

O host, que carrega o bundle e executa as functions e os commands:

{% code lineNumbers="true" %}

```typescript
// src/main.ts
import { createSkailPlatform } from "@skail/runtime";

const controller = new AbortController();
for (const signal of ["SIGINT", "SIGTERM"] as const) process.once(signal, () => controller.abort());

const platform = createSkailPlatform({
  bundle: new URL("../.skail/app/skail-functions.mjs", import.meta.url),
  manifest: new URL("../.skail/app/manifest.json", import.meta.url),
});
await platform.run(controller.signal);
```

{% endcode %}

O host lê o workload, o namespace, a chave e o endereço do skail das variáveis `SKAIL_*`. O `SKAIL_WORKLOAD` precisa ser igual ao `--workload` usado no build.

A referência do host está em [Configuração do host](/referencia/sdk-csharp/configuracao-do-host.md).
{% endtab %}
{% endtabs %}

## Regras do SDK

As regras de fundo valem para todas as linguagens e estão em [Modelo de programação](/construa/conceitos/functions-e-commands.md) e [Determinismo e replay](/construa/conceitos/replay-e-determinismo.md). O que cada SDK pede no código:

{% tabs %}
{% tab title="C#" %}

* Functions e commands são métodos `public`, de instância e `async`, com `[SkailFunction]` e `[SkailCommand]`, e retornam `SkailTask` ou `SkailTask<T>`.
* `SkailTask.WhenAny` devolve a espera que terminou primeiro; o prazo vencido é testado comparando o resultado com a espera do delay.
* Dentro de uma function, `DateTime.UtcNow`, `Guid.NewGuid()`, `Random`, `Task.Delay` e `Task.WhenAll` compilam, mas quebram o replay: o que não é determinístico vai para um command.
* As classes são registradas no contêiner de injeção de dependência por `UseSkail()`, e as dependências entram pelo construtor.
  {% endtab %}

{% tab title="TypeScript" %}

* Functions e commands são métodos públicos, de instância e `async`, com `@SkailFunction()` e `@SkailCommand()`, e retornam `Promise<T>`; o `skail build` rejeita métodos `static`, `private` ou sem `async`.
* `Skail.whenAny` resolve com o valor de quem terminou primeiro, e o delay resolve `undefined`. Por isso o prazo vencido é testado com `=== undefined`, e o payload do evento não pode ser `undefined`.
* Dentro de uma function, `new Date()` sem argumento, `Date.now()`, `Math.random()`, `crypto.randomUUID()`, `setTimeout()` e `fetch()` lançam erro: o que não é determinístico vai para um command.
* `process.env` só pode ser lido dentro de um command. No topo de um módulo que entra no bundle, no `useFactory` dos `providers` e na function, a leitura lança erro, e um erro no carregamento do módulo impede o host de subir. Leia a variável no command que a usa.
* O runtime não infere parâmetros de construtor: as dependências são ligadas por `providers` (`useFactory`) ou instanciadas na classe.
  {% endtab %}
  {% endtabs %}

## Em breve

Java, Python e outras linguagens.

## Qualquer linguagem pela API HTTP

Ter ou não SDK não impede que um sistema participe dos fluxos. Iniciar uma function e disparar um evento são dois `POST` na API HTTP, de qualquer stack. Na prática, um fluxo típico tem o orquestrador escrito com o SDK e os sistemas que iniciam o fluxo e disparam eventos (o front-end que aprova, o webhook que confirma, o job que inicia) em qualquer linguagem. [Chamar o skail de qualquer linguagem por REST](/construa/como-fazer/chamar-o-skail-de-qualquer-linguagem-por-rest.md) mostra como.

## Próximos passos

[Quickstart](/comece-aqui/quickstart.md) para rodar o primeiro fluxo. [Chamar o skail de qualquer linguagem por REST](/construa/como-fazer/chamar-o-skail-de-qualquer-linguagem-por-rest.md) e a referência de [POST /api/v1/trigger](/referencia/api-http/post-trigger.md) e [POST /api/v1/fire](/referencia/api-http/post-fire.md).
