ICO
ICO (Input → Context → Output) builds computation flows from typed operators. A flow is a tree that you can describe before it runs, run in one process, in worker processes or on a cloud GPU, profile, watch in the browser, and save as JSON. State that changes item by item, such as a model during training, is data in the flow, not a hidden field.
from ico import IcoProcess, operator
State = tuple[int, int]
@operator()
def fib_step(state: State) -> State:
a, b = state
return (b, a + b)
@operator()
def first(state: State) -> int:
return state[0]
fib8 = IcoProcess(fib_step, num_iterations=8) | first
fib8((0, 1)) # 21
fib8.describe()
How it is built
flowchart TB
R["IcoRuntime"] --- T["tools: Live Board, profiler, progress"]
R -- "commands: activate, run, cancel" --> flow
flow -- "events: progress, profile, errors" --> R
subgraph flow["IcoProcess: 3 epochs"]
direction LR
subgraph epoch["IcoFold: one epoch"]
direction LR
S["IcoSource"] --> P["IcoProgress"] --> A["IcoAsyncStream"] --> F["train_step"]
A -.- W["MPWorker × 4: load"]
end
end
Operators. An IcoOperator[I, O] wraps a callable from I to O.
Signatures are inferred from annotations and generics and checked at every
link: validate_signatures(flow) reports mismatches, and mypy or Pylance
check the same types statically.
Composition. a | b chains operators. A few structural nodes cover the
rest:
| Node | Type | |
|---|---|---|
IcoSource, IcoSink |
() → Iterator[O], Iterator[I] → () |
ends of a flow |
op.stream() |
Iterator[I] → Iterator[O] |
map over items |
IcoAsyncStream(factory, pool_size) |
Iterator[I] → Iterator[O] |
a pool, threads or worker processes |
fork, route, keep, partition, tap |
fan out, choose by key, filter, split, side effect | |
IcoBatcher(n) |
Iterator[I] → Iterator[Iterator[I]] |
batches |
IcoFold(source, step) |
C → C |
step((item, state)) for each item: a training epoch |
IcoProcess(body, ...) |
C → C |
repeat n times or until a predicate |
IcoProgress(total) |
I → I |
counts the items that pass it |
Two trees. The flow tree computes. The runtime tree (IcoRuntime)
activates it, sends commands down (activate, run, cancel) and events up
(progress, prints, profiles, errors). Tools attach to the runtime: Rich
progress, the Live Board, the profiler, samples of the results of a node.
A cancelled run stops between items.
Workers. MPWorker(factory) runs a sub-flow in its own process; inside
an IcoAsyncStream it is a pool. Its progress and profile come back to the
main runtime, and the plan shows its flow.
Specs and the registry. Operators registered with register("name", 1)
are parametric and versioned. ico.spec.to_spec(flow) turns a flow into
JSON, and build(spec) builds a flow from a spec of registered operators.
Specs take parameters ({"$param": ...}) and can refer to other saved
pipelines.
Remote runs. ico.remote runs a spec as a job in a subprocess or on a
RunPod Serverless GPU. The job carries the operators' code by value, its
inputs go through S3 or a network volume, and its events stream back to the
same tools.
Assets and resources. Model weights are pinned assets (assets.toml,
assets.lock, ico assets fetch). Loaded models are resources in a pool
per process, with a RAM budget, shared by the operators that use them.
Live Board and profiler
from ico import IcoRuntime, LiveBoardTool
from ico.tools.profiler import instrument
board = LiveBoardTool(profile=True)
flow = instrument(flow, board.profiler)
IcoRuntime(flow, tools=[board]).activate().run().deactivate() # prints the URL
The board shows every progress node, worker processes included, the plan
with each node's time, calls and p95, and the models each process holds.
Below, the CIFAR-10 example during training: four MPWorkers load and
augment batches, two folds train and validate, and train_step takes 95% of
the work.
MCP server
ico-mcp is an MCP server on top of ICO. An agent finds operators in a domain's registry, composes and validates specs, runs them locally or on a GPU target and follows them on the Live Board. It writes new operators as drafts, and once a pipeline works it opens a pull request that makes them stable.
Examples
- ICO basics and the runtime (notebooks)
- Worker processes and a pool of them
- A training process in miniature: a pool of worker processes loads items, a fold runs an epoch over them, a process repeats it (the diagram above)
- Linear regression
- CIFAR-10: notebook,
with worker pools
(
--epochs 1 --limit 4000 --profilefor a quick run with the profiler)
Worker processes do not run in Jupyter or Colab: run those examples from a terminal.
Installation
pip install apriori-ico
or, for development, uv sync in a clone (make ci runs the checks).
| Extra | Installs | For |
|---|---|---|
remote |
boto3 |
remote runs (S3, RunPod volumes) |
vision |
torch, torchvision, matplotlib |
the CIFAR-10 examples |
examples |
skrub, pydot, graphviz |
the skrub examples |
notebook |
ipywidgets |
Rich widgets in Jupyter |
Design notes are in docs/design.
License
Apache License 2.0, see LICENSE.
Metadata
Release files for apriori-ico 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| apriori_ico-0.1.0.tar.gz | 233.3 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| apriori_ico-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 543.0 kB
Release files / apriori_ico-0.1.0.tar.gz
| Download URL | apriori_ico-0.1.0.tar.gz |
|---|---|
| Size | 233.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
73c8ebaf9570cf3b1a502da85fba0e7ac63e5daaf00da42f6188dd71c767c0f9
|
|
BLAKE2b-256 checksum How to use checksums |
ffa00f0d4b8bb180181d490a13fab08ec6055c2ee3e5cdc07c72c5e43af6c1df
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 22, 2026.
Transparency logRelease files / apriori_ico-0.1.0-py3-none-any.whl
| Download URL | apriori_ico-0.1.0-py3-none-any.whl |
|---|---|
| Size | 309.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
cda5aaa6677b5834cd53afec1bcd78eeb51b04ea8eccc1779e7808b3d355a8af
|
|
BLAKE2b-256 checksum How to use checksums |
063648dad61c28183cbacca289bac95aa066f913e39ac44adb7e0657db61da63
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 22, 2026.
Transparency logSecurity for apriori-ico 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for apriori_ico-0.1.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 22, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.