Skip to content

Share a capability across contexts

Goal: write a capability once — a Clock, an Http client, a Random source — in a platform context, and let application contexts depend on it without re-declaring or re-implementing it.

Export the capability from the providing context

Section titled “Export the capability from the providing context”

The providing context declares and provides the capability as usual, then lists it in an exports capability { … } clause:

context platform.time
exports capability { Clock }
capability Clock {
fn now() -> Effect[Int]
}
provides Clock = SystemClock {
fn now() -> Effect[Int] {
0
}
}

Only a capability the context both declares and provides may be exported (otherwise a consumer could not instantiate it).

The consumer consumes the providing context and depends on the capability through a qualified given — the same prefix is used for the call:

context ops.jobs
consumes platform.time
service tick {
on call() -> Effect[Int] given platform.time.Clock {
let t <- platform.time.Clock.now()
t
}
}

Prefer an alias for brevity when the context path is long:

consumes platform.time as Time
-- ...
on call() -> Effect[Int] given Time.Clock {
let t <- Time.Clock.now()
t
}

A consumer’s provider may depend on a cross-context capability too: provides Stamp = ClockStamp given platform.time.Clock { … }.

The capability’s contract is imported for type-checking; its provider is instantiated in the consumer’s own composition — in the shared root (bundle) or imported into the consuming Worker (workers). The call runs in-process (deps.Clock.now()), so each consuming Worker gets its own instance — exactly what stateless platform capabilities want. No Worker hop is involved.