Concepts
The few ideas behind Laser SDK: streams, topics, partitions, agents, sessions, and the managed plane
Laser SDK keeps everything on one log. Messages, agent requests and replies, session records, and memory are all records on topics in Apache Iggy. Read this page once and the guides will make sense.
Stream
A stream is the isolation boundary. It groups topics and owns their permissions. A session and all of its child sessions live in one stream, and no read, link, or derived id crosses streams. Use one stream per application or tenant.
Most agent calls need a default stream. Set it when you connect, for example with connect_with_stream (TypeScript connectWithStream). Managed names such as key-value namespaces and graphs are scoped to that stream as stream:<stream>/<name>. See Connect.
Topic
A topic is a named log inside a stream. Producers append records to it and consumers read them back. The call bootstrap(partitions, retention) creates the agent topics: agent.sessions for requests, replies, and session records, plus agent.heartbeats, agent.streams, agent.memory, agent.dlq, agent.audit, and agent.workflow_journal. You create your own topics for your own data. See Messages.
Partition
A topic is split into partitions. Order holds only within one partition. Records with the same partition key land on the same partition, so they stay in order. Records without a key are spread across partitions.
In the default layout, the SDK keys every agent record by its session. All records of one session land on one partition of agent.sessions, in the order they were written. That ordered slice is the session lane. Lifecycle and state records stay on the lane in every layout.
Message and offset
A message is one record: a payload, headers, and a timestamp. Its offset is its position in the partition. Offsets start at 0 and only grow. A partition id plus an offset names one message exactly, and the SDK calls that pair a message id.
Records stay on the log until the topic's retention removes them. Agent topics that bootstrap creates never expire, except agent.sessions, which uses the retention you pass, and agent.heartbeats, which expires after one hour.
Consumer group
A consumer group is a set of readers that share a topic. Each partition goes to one member at a time. The group stores how far it has read, its committed offset, so a restarted reader continues where the group stopped.
Agent
An agent is an id plus a handler. It joins its own consumer group, named after the agent id, and runs the handler for each record addressed to it. Replies, status records, and records for other agents are skipped.
The runtime commits a record only after the handler succeeds. If the process crashes, the record is delivered again. Failed handlers are retried, by default up to 5 attempts starting at a 200 ms delay. A record that still fails goes to agent.dlq. An agent can advertise capabilities, so a caller can route work to "any agent that can resolve tickets" instead of a fixed name. See Agents.
Session
A session is one unit of work with a recorded lifecycle. It records the requests, replies, model calls, tool calls, and state changes of that work on its lane, so you can read it back or replay it later. Its id is the conversation id that every record of the session carries.
A session has one of these statuses. The SDK and the session index spell them in lowercase, such as canceled.
| Status | Meaning |
|---|---|
| Submitted | Work was handed to an agent that has not picked it up yet |
| Active | An agent is working on it |
| Paused | An operator paused it, and agents hold new work for it |
| Completed | The owning agent ended it successfully |
| Failed | It ended with an error or a rejection, or an agent or workflow stopped it for going over budget |
| Canceled | It was canceled |
Work with its own lifecycle runs as a child session. A workflow run is a root session, and each step is a child. A contract can run as a child of the session that sent it. Child sessions stay in the parent's stream. See Sessions.
Managed plane
Plain Apache Iggy runs everything that only needs the log: messages, agents, contracts, workflows, sessions, and memory folded from the log. Other features need the LaserData Apache Iggy fork and laser-plane, a service that reads the log and builds views from it. Laser Stack runs both locally, and LaserData Cloud runs them in production.
| Feature | Plain Apache Iggy | Laser Stack or Cloud |
|---|---|---|
| Messages, agents, contracts, workflows | Yes | Yes |
| Session records, lane reads, replay | Yes | Yes |
| Session index, lists, and timelines | No | Yes |
| Memory folded from the log | Yes | Yes |
| Managed memory view | No | Yes |
| Server-side filters | No | Yes |
| Queries and views, changes | No | Yes |
| Key-value state, forks, graph | No | Yes |
| Managed permissions | No | Yes |
Capabilities
At connect, the client asks the server what it serves and keeps the answer as capabilities. Read them with laser.capabilities(). When the answer has no managed plane, a read at least one second after the last probe asks again, so a backend that comes up later is picked up. A managed call that the server does not serve fails with an unsupported error (Rust LaserError::Unsupported, Python and TypeScript UnsupportedError). Nothing falls back silently. Check a capability first when your code must run on both plain Apache Iggy and a managed deployment.