Skip to content

Callbacks

Callbacks let a downstream node send data back to an upstream service that is still running. This enables bidirectional communication within a task — a service can pause, wait for a response from a later node, and then continue based on that response.

Callbacks are useful when a service needs input from a downstream node before it can proceed:

  • A service generates options → a logic node selects one → the service continues with the selection
  • A service requests approval → a downstream step decides → the service acts on the decision
  • A service emits partial data → a logic node enriches it → the service incorporates the result

1. The Service Creates and Yields a Callback

Section titled “1. The Service Creates and Yields a Callback”
import { createService, createCallback } from '@requence/service'
createService('1.0.0', async function* (ctx) {
const callback = createCallback<number>()
// Yield the callback as part of the output
yield { chooseAmount: callback }
// Wait for the downstream node to respond
const amount = await callback.response()
// Continue with the received value
yield ctx.toOutput('result', { total: amount * 10 })
})

The callback arrives as a callable function on the downstream node’s input. Calling it sends the value back to the waiting service:

// Logic node script
context.input.chooseAmount(42)

After the downstream node invokes the callback, callback.response() resolves with the value (42 in this example). The service can then continue its execution and yield further results.

A complete task template using callbacks might look like this:

  1. EntryService (generator, yields a callback) → Logic (invokes callback) → Exit
  2. The service also has a named output result that connects directly to the exit
// Service handler
createService('1.0.0', async function* (ctx) {
const callback = createCallback<number>()
yield { multiply: callback }
const factor = await callback.response()
yield ctx.toOutput('done', { result: factor * 100 })
})
// Logic node script
context.input.multiply(10)

The task completes with { result: 1000 }.

A service can create and yield multiple callbacks, either sequentially or in the same yield:

createService('1.0.0', async function* (ctx) {
const approve = createCallback<boolean>()
const setAmount = createCallback<number>()
yield { approve, setAmount }
const [approved, amount] = await Promise.all([
approve.response(),
setAmount.response(),
])
if (approved) {
yield ctx.toOutput('confirmed', { amount })
}
})

createCallback is also available as a global inside logic nodes — see Logic Nodes.