| operator into a pipeline, and run that pipeline sync or async with one call.
The runnable contract
Every runnable implements the same small protocol, defined ininfy/core.py. That is the entire contract:
Protocol, anything with these methods is a runnable. There is no base class to inherit from.
Every method takes an optional
ctx (a Context). Leave it out and the runnable uses defaults. See Context below.Piping into a Sequence
The| operator chains runnables left to right into a Sequence. Each step receives the previous step’s output.
Sequence runs its steps in order, threading the result through:
ainvoke awaits each step in turn, so an async chain never blocks the event loop. Sequence also flattens: piping two sequences together produces one flat Sequence, not a nested one.
Automatic coercion
You rarely construct runnables by hand. When you pipe something that is not already a runnable,coerce (in infy/core.py) converts it:
So a bare function drops straight into a chain:
Lambda automatically. Piping a callable that coerce cannot handle raises TypeError.
Lambda
Lambda wraps a synchronous function as a runnable. Its invoke calls the function directly; its ainvoke runs the function in an executor so a sync function does not block the loop.
AsyncLambda, whose ainvoke awaits the function directly. The async coercion helper acoerce picks AsyncLambda automatically for coroutine functions.
Parallel: fan out on one input
Adict in a chain becomes a Parallel. Each value is coerced to a runnable, every branch receives the same input, and the result is a dict with the same keys.
dict and let coercion build the Parallel for you:
invoke runs them across a ThreadPoolExecutor; ainvoke runs them under asyncio.gather. Both honor max_concurrency from the Context when set.
Context and concurrency
Every runnable method accepts an optionalContext. It carries tags, metadata, and max_concurrency, and passes down through a chain.
Parallel, max_concurrency caps how many branches run at once (a semaphore under ainvoke, the thread-pool size under invoke). Leave ctx as None and each Parallel defaults to running all of its branches at once.
Streaming through a chain
Runnables also exposestream and astream. A Sequence streams by piping each step’s output into the next, yielding chunks as they arrive.
Chat models
The
ChatModel protocol every provider implements, and how it plugs into a chain.Structured output
Parse and validate model output with
JsonParser or a pydantic model.