Success · Receipt
What it produces
The value a successful run hands back. Use, yield from charge(order) and possible errors automatically propagate. Just like with async / await code.
Effecton
With Effecton33 lines
import effecton as E
class TooLate(E.EffectonError): ...
class Closed(E.EffectonError): ...
@E.gen
def greet(
name: str,
) -> E.EffectGen[str, TooLate | Closed]:
now = yield from E.now()
if now.weekday() == 6:
yield from E.fail(Closed())
if now.hour >= 22:
yield from E.fail(TooLate())
return f"hello {name}"
program = (
greet("ada")
.retry( # typesafe retries
E.Schedule.spaced(minutes=1),
until=lambda e: isinstance(e, Closed),
)
.with_span( # observability built in
"greet"
)
)
E.run_main(program)Add a guarantee
Without Effecton9 lines
import httpx
async def fetch_profile(
client: httpx.AsyncClient, user_id: int
) -> str:
response = await client.get(f"/users/{user_id}")
response.raise_for_status()
return response.textWith Effecton17 lines
import effecton as E
type FetchError = (
E.HttpClient.TransportError | E.HttpClient.StatusError
)
@E.gen
def fetch_profile(
user_id: int,
) -> E.EffectGen[str, FetchError, E.HttpClient.Protocol]:
http = yield from E.require(E.HttpClient.Protocol)
response = yield from http.get(f"/users/{user_id}")
ok = yield from E.HttpClient.filter_status_ok(response)
return ok.textdef charge(
order: Order,
) -> E.Effect[
Receipt,
CardDeclined | CardExpired,
PaymentGateway,
]: ...
Success · Receipt
The value a successful run hands back. Use, yield from charge(order) and possible errors automatically propagate. Just like with async / await code.
Error · CardDeclined | CardExpired
Every expected failure, as a union of plain classes. Implement granular, type-safe error handling with catch(CardExpired).
Requirements · PaymentGateway
The services the program depends on. Inject Live dependencies in your production code and mocks in tests. Type checker knows when you forget to do so.
Every function says what it returns, how it can fail and what it needs, right in its signature. You and your agent sees the whole interface.
Agents love building from reusable building blocks. Small, typed, composable primitives are easy for a model to reason about.
Just point it to the docs. Your agent is already effecton expert.
Building blocks
What they add up to
Typed handlers with built-in retries and tracing
Testable side effects, structured errors
Reliable steps that retry, time out, and log themselves