SSSN: the network module
SSSN, the Simple System of Systems Network, connects systems through
channels. A channel is a named stream of records: producers append to it,
consumers read it at their own pace, and every record can point back at the
records it came from. A tactic is one system; channels are how its inputs
arrive and its outputs leave. In code, SSSN is lllm.network.
SSSN is an experimental module of LLLM.
pip install "lllm-core[server,client]" # adds the FastAPI store server and the HTTP clients
The data model, LocalStore, and TacticProcessor need only lllm-core.
Five resources
All five are Pydantic models exported from lllm.network, and every store
(LocalStore, RemoteStore, AsyncRemoteStore) reads and writes them with the
same method names.
A channel in ten lines
from lllm.network import Channel, Event, LocalStore
store = LocalStore(".lllm/network")
store.create_channel(Channel(name="inbox", description="Support messages."))
store.append_event(Event(channel="inbox", kind="message", payload={"text": "Checkout is down"}))
store.append_event(Event(channel="inbox", kind="message", payload={"text": "How do I export data?"}))
for event in store.query_events("inbox"):
print(event.cursor, event.payload["text"])
1 Checkout is down
2 How do I export data?
LocalStore keeps a whole store in one folder: SQLite for channels, events,
subscriptions, and snapshots, and plain files for artifact bytes. Serve that
folder with lllm network serve and any process can use it through
RemoteStore, which has the same methods.
Tactics over channels
TacticProcessor joins the two halves of LLLM. It reads a channel through a
named subscription, runs each event's payload through a tactic, and appends the
output to a sink channel with a pointer back to the input. Continuing the
example:
from lllm import as_tactic
from lllm.network import TacticProcessor
def triage(ticket: dict) -> dict:
urgent = "down" in ticket["text"].lower().split()
return {"priority": "urgent" if urgent else "normal"}
store.create_channel({"name": "triaged"})
processor = TacticProcessor(
as_tactic(triage), store, source="inbox", sink="triaged", consumer="triage"
)
for result in processor.process():
origin = store.get_event(result.parent_ids[0])
print(result.payload, "<-", origin.payload["text"])
{'priority': 'urgent'} <- Checkout is down
{'priority': 'normal'} <- How do I export data?
Call processor.process() again and it returns []: the triage
subscription lives in the store and remembers where it stopped, across
restarts and across processes. Any tactic works here, including native tactics
with agents and remote tactics (see The Tactic).
Processing covers resuming, failures, async workers, and
multi-stage pipelines.
How the pieces fit
| You want to | Use | Read |
|---|---|---|
| Model channels, events, subscriptions, artifacts, snapshots | Channel, Event, Subscription, Artifact, Snapshot |
Channels and stores |
| Keep a store on disk | LocalStore |
Channels and stores |
| Run a tactic over a channel | TacticProcessor |
Processing |
| Serve a store over HTTP, add routes | create_app, endpoint |
Serving |
| Use a served store from another process | RemoteStore, AsyncRemoteStore |
Serving |
Name channels with lllm:// refs |
ChannelRef, ChannelResolver, lllm.Resolver |
Serving |
| Work from the shell | lllm network --store DIR <command> |
Serving |
| Mount channels next to tactics in one API | lllm.shell |
AAAX |
Status
Names and wire formats may change between releases. Current limits worth knowing before you build on it:
- One storage backend:
LocalStore(SQLite plus files). The HTTP server and clients put any process in front of it. - Consumers poll. There is no push delivery or blocking pull.
pull_subscriptionmoves the cursor as it returns events, so a consumer that pulls directly gets each event at most once.TacticProcessoracknowledges an event only after writing its output, so its delivery is at least once: an event cut short by a raised error or a crash runs again, and its output can appear twice. Processing shows how to keep failures visible.- The store server has no authentication. Bind it to localhost or put it behind your own gateway.
Next
- Channels and stores: every resource and the
LocalStorelayout. - Processing:
TacticProcessorin depth and pipelines. - Serving: the store server, clients, refs, and the CLI.
- Tutorial 11: Channels with SSSN: build a small system end to end.