Skip to main content

Managed streaming

SDK 0.4.0 supports managed providers in all four I/O modes. Streaming uses a fresh authenticated media connection per invocation, independent of health.

ModeCaller inputProvider output
UnaryOne JSON requestOne result
Server streamingInitial JSON requestChunks, then terminal
Client streamingInitial request, input chunks, input terminalOne final output terminal
BidirectionalInitial request, input chunks, input terminalChunks, then output terminal

Implement the child handler​

When the primary IPC loop receives StreamInvoke, start an owned task calling execute_stream(startup, message, handler). Continue answering Health; cancel and await your owned task on shutdown or primary-channel loss.

from collections.abc import AsyncGenerator, AsyncIterator
from skulk_capability_sdk.contracts import StreamInvoke
from skulk_capability_sdk.streams import StreamFrame

async def echo_stream(
call: StreamInvoke,
inputs: AsyncIterator[StreamFrame],
) -> AsyncGenerator[StreamFrame]:
sequence = 1
async for frame in inputs:
if frame.kind == "chunk":
yield StreamFrame(
call_id=call.call_id,
direction="provider_to_caller",
sequence=sequence,
kind="chunk",
payload=frame.payload,
media=frame.media,
)
sequence += 1
if frame.is_terminal:
break
yield StreamFrame(
call_id=call.call_id,
direction="provider_to_caller",
sequence=sequence,
kind="completed",
)

This bidirectional example requires matching input/output chunk schemas. Skulk™ owns output started at sequence zero. Your handler starts at one, emits exactly one terminal, and returns. Cleanup finishes before the helper publishes the terminal and private acknowledgment. Extra frames after a terminal are rejected.

Half-close, cancellation and bounds​

Caller input completed carries no payload or media and half-closes input while output remains open. Caller cancellation or disconnect cancels the invocation. Use try/finally for provider resources and keep blocking work off the event loop. Provider output completion stops input forwarding before cleanup closes the media connection.

  • One active invocation per child, shared by all modes.
  • One stream deadline, capped at 300 seconds by Bounds.stream_seconds.
  • Each packet has a four-byte network-order header length, at most 64 KiB of finite JSON, then at most 1 MiB of raw inline media. Bytes never appear in JSON.
  • Eight-frame ingress queues and awaited socket writes apply backpressure.
  • The helper uses only the owner-provisioned Startup.stream_socket, process token, installed identity, manifest digest and fresh local call identity.
  • Wrong identity, sequence, schema or framing fails the call. Failed processes follow normal supervision and restart budgets; work is never replayed.
  • Media stays out of replicated State and event logs. Blob attachments remain immutable references; the bridge does not open caller-supplied files.

Deploy the compatible Skulk™ reader before enabling protocol-4 streaming bundles. Rebuild immutable runtimes with the compatible SDK and qualify signed installation separately from source tests. Protocol 3 unary children remain compatible for one release cycle; protocol 2 requires rebuilding.

The managed host callback channel is a fixed unary management interface. General Fabric clients use the public caller contract. This SDK's streaming interface serves those calls from managed children.

Streams API reference