# async / await — why Osy# has neither

> Osy# has no async and no Task. A function that calls out to the world is written like any other function — the engine suspends and resumes it around the effect. await exists in exactly one place, Workflow.Run.

<!-- id: function-async-await · area: function · stability: stable · html: https://osysharp.com/reference/function/async-await/ -->

## Summary        {#summary}
**There is no `async` in Osy#, and no `Task<T>`.** A function that calls out to the world — an HTTP request, an LLM
completion — is written exactly like one that adds two numbers. You call the thing; the platform takes care of the
waiting.

`await` exists in **one** place in the whole language: `await Workflow.Run("step", …)`.

If you are coming from C#, this is the first thing to unlearn, so it is worth a page of its own.

## Signature      {#signature}
```osy syntax
// No `async`. No `Task<T>`. No `.Result`, no `ConfigureAwait`, no `Task.WhenAll`.
<ReturnType> <Name>(<params>) {
  var r = Http.Get(url);      // an effect — just call it
  …
}

await Workflow.Run("step", <workflow>);   // the ONE await: wait for another long-running thing to finish
```

## Description    {#description}

### Just call the effect   {#just-call}
An **effect** is anything that reaches outside the database: an HTTP call, a model completion, a file read. You call
it. That is all:

```osy title="calling out, with no ceremony" test app=function-async-await
app Shop {
  model "model/**/*.osy";
  use Osysharp.Http;
}

entity Order {
  [Required] string Code;
  bool Notified;
}

void Notify(string code, string url) {
  var order = Order.Single(o => o.Code == code);
  var r = Http.Get(url);         // the function pauses here — but you did not have to say so
  order.Notified = r.IsSuccess;
}
```

The function does not return a `Task`. Its caller does not `await` it. Nothing about its signature says it might take
a while.

### What happens when a function hits an effect?   {#what-happens}
When a function reaches an effect, the engine **suspends** it, performs the effect, and **resumes** it at the very
next line — with every local still in place. That suspension is *durable*: if the process is restarted, redeployed or
killed while the HTTP call is in flight, the function still resumes where it left off. It is not a thread parked in
memory; it is a continuation the platform persisted and will pick up again.

That is a stronger promise than `async` makes. A C# `async` method whose process dies mid-await is simply gone.

### Why is there no `async` colour to propagate?   {#colour}
In C#, `async` is a **colour**. A method that awaits must be `async`, so its callers must `await` it, so *they* must
be `async`, and it spreads outward until it has reached `Main`. You end up marking a hundred functions to describe a
property of one — and then a library forces you into `.Result` and you deadlock a thread pool at 4am.

The colour exists so that a *caller* knows the callee might yield. Here, that is the engine's business rather than the
signature's: any function can suspend, so no function has to advertise it. There is nothing to spread, so there is
nothing to mark.

The practical consequence: **the ability to call out to the world costs you nothing in your function signatures.** You
can add an HTTP call to a function three layers down and not touch a single caller.

### The one place `await` is legal — `Workflow.Run`   {#the-one-await}
`await Workflow.Run("step", …)` is the exception, and it earns it. There, waiting is the thing you are actually saying: *start
this other long-running process, and do not continue until it is finished.* It may be finished in ten seconds or in
three weeks; the `await` is what says you are content to wait either way.

That is a decision about your business process, not a detail of your threading — which is exactly why it is the one
place the word appears.

### If you write `async` or `await` anyway   {#tolerated}
The compiler stops you. `async` is a parse error — *"Osy# has no `async` — effects run in place, so a function or
method is never marked `async`."* `await` is an error everywhere except the one place it means something
(`await Workflow.Run("step", …)`) — *"Osy# has no `await` — effects run in place, so `await` is never needed."* Both messages
point you straight back to this rule. There is no tolerated middle ground: the word suggests a distinction that does
not exist, so the compiler removes the temptation rather than letting it read as meaningful.

## See also       {#see-also}
- [function](https://osysharp.com/reference/function/declaration/) — how a function is written
- [Http.*](https://osysharp.com/reference/http/facade/) — `Http.Get` / `Http.Post`, the effects you call without ceremony
- [subscribe](https://osysharp.com/reference/workflow/subscribe/) — long-running processes, where waiting is the point
