> Canonical guide: https://developers.foxlight.ai/build/examples/streaming/
> Contract snapshots: Skulk 2.0.0 (b0af39c79b6b7102b2478062904f1d7cc8619975); SDK 0.4.0 (31bb090b8f64689f87514e48385e22b6ad94a6c2). Check the installed runtime when versions differ.

# Duplex echo example

Use the [managed streaming handler](https://developers.foxlight.ai/build/sdk/streams/#implement-the-child-handler) as the smallest duplex example. It is a handler, not a standalone child. Its descriptor needs `io_mode="bidirectional"` and both input and output chunk schemas; the initial request schema is separate from each chunk schema.

## Wire it into the control loop

On `StreamInvoke`, start an owned task with `streams.execute_stream(startup, message, handler)`. Keep answering `Health` on the primary connection. On shutdown or lost control connection, cancel and await the task before closing resources. Do not put the entire stream inline inside the health loop.

## Exercise the caller sequence

1. Discover the descriptor and negotiate its exact id, version and revision.
2. Open through the Fabric caller API and check `open_result.ok` before sending input.
3. Consume provider frames while sending bounded input chunks.
4. Call `session.input.complete()` to half-close input.
5. Keep reading output until its terminal; inspect failure or cancellation, not just the chunks received.

[`skulk.extensions` caller examples](https://developers.foxlight.ai/build/calling-and-streaming/) show this side of the contract. A managed child does not directly create that caller context. The host callback channel is a fixed management contract; it is not a general-purpose Fabric streaming client.

## Cases to test

Send zero chunks, one chunk and many chunks. Try a slow output consumer, cancel while input is open, lose the media connection and send an invalid chunk. Confirm ordered output begins at sequence one after Skulk’s `started` frame, exactly one terminal is emitted and cleanup finishes before successful terminal delivery.

Raw media remains binary. Do not base64 it into JSON or publish it as application telemetry. See [streams reference](https://developers.foxlight.ai/build/sdk/reference/streams/) for exact helper signatures and bounds.
