org.llm4s.agent.graph

Members list

Type members

Classlikes

object Breakpoint

Attributes

Supertypes
class Object
trait Matchable
class Any
Self type
Breakpoint.type

Where a static breakpoint holds a task: before its node runs, or after it ran.

Where a static breakpoint holds a task: before its node runs, or after it ran.

A run's RunConfig.interruptBefore and RunConfig.interruptAfter name the nodes. A task held before its node runs has done nothing; once its interrupt is answered it runs, and that breakpoint does not hold it again. A task held after its node ran has its update committed, so the state shows what it did, but its routes, static edges and join arrivals wait: once its interrupt is answered they are made, without running the node again. Either way the held task is parked like a task that suspended - one interrupt per task, keyed by its task id - and the run pauses at the end of the superstep, so breakpoints and typed interrupts are answered together, any non-empty subset at a time.

Attributes

Supertypes
trait Enum
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
final case class CachePolicy

Declares that a node's result depends only on its input, so a repeated input may be answered from memory without running the node.

Declares that a node's result depends only on its input, so a repeated input may be answered from memory without running the node.

The node must not depend on ThreadState, on the clock, or on an external system: a node that needs part of the state takes that part as input. The key is the node, its input schema version and the encoded input. A hit returns the stored Command and the node does not run, so a cached node should not rely on RunContext.emit or progress. Only a Continue result is stored: a failure or a suspension is not.

The cache belongs to the CompiledGraph instance and is shared by its runs. It is not checkpointed, so another instance, another process or a restart starts empty and recomputes. Entries beyond maxEntries are evicted least-recently-used first. Two tasks with one input running at the same time both run the node.

Every value is validated like RunBudgets: apply and the with* setters throw IllegalArgumentException; CachePolicy.of returns a ValidationError.

Value parameters

maxEntries

the most results kept for the node

ttl

how long an entry is served after it was stored; None means until evicted

Attributes

Companion
object
Supertypes
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
object CachePolicy

Attributes

Companion
class
Supertypes
trait Product
trait Mirror
class Object
trait Matchable
class Any
Self type
final case class Checkpoint

One durable point in a thread's execution - data only. Closures, codecs and update functions are rebound from the compiled graph on restore; every value inside carries the version of the codec that wrote it (VersionedJson).

One durable point in a thread's execution - data only. Closures, codecs and update functions are rebound from the compiled graph on restore; every value inside carries the version of the codec that wrote it (VersionedJson).

parent is the checkpoint this one supersedes. A checkpointer accepts a new checkpoint only if parent is the thread's latest, so two writers cannot both advance one thread: the latest checkpoint's id is the thread's version. fencingToken is the token of the claim whose run wrote it (RunClaim); None on checkpoints written before claims existed (format 4 and earlier).

Persist with Checkpoint.toJson and read with Checkpoint.fromJson, which migrates older formatVersions and refuses newer ones.

Attributes

Companion
object
Supertypes
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
object Checkpoint

Attributes

Companion
class
Supertypes
trait Product
trait Mirror
class Object
trait Matchable
class Any
Self type
Checkpoint.type

Whether a thread's latest checkpoint is mid-execution or finished its run.

Whether a thread's latest checkpoint is mid-execution or finished its run.

Attributes

Supertypes
trait Enum
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
trait Checkpointer

Durable storage for graph threads: each thread's checkpoint history, the pending writes recorded against its latest checkpoint, its durable event log, and the claim of the run that holds it. One store owns all of them so that a commit is atomic and fenced. Several GraphRuntimes, in one process or many, may share a store: the claim is what keeps two of them from running one thread at once.

Durable storage for graph threads: each thread's checkpoint history, the pending writes recorded against its latest checkpoint, its durable event log, and the claim of the run that holds it. One store owns all of them so that a commit is atomic and fenced. Several GraphRuntimes, in one process or many, may share a store: the claim is what keeps two of them from running one thread at once.

Implementations must be safe to call from several threads and processes, and must:

  • grant at most one live claim per thread (claim): a claim is live until its expiresAt, by the store's own clock, has passed; a request while one is live is refused with GraphError.ThreadBusy naming its holder, and an expired claim is replaced - taken over;
  • issue each claim a FencingToken strictly greater than every token issued for that thread before - across releases, takeovers and deleteThread - so a token is never reused;
  • apply a Commit entirely or not at all, and only if its token is the thread's current claim (GraphError.StaleClaim otherwise, checked first) - so a writer that lost its claim, even one whose token is the highest it has seen, records nothing after another run took over;
  • accept a new checkpoint only when its parent is the thread's latest checkpoint id - the thread version the writer expects (GraphError.CheckpointConflict otherwise) - and its id is not already in the thread's history, and only pending writes naming the resulting latest checkpoint (GraphError.InvalidCommit);
  • keep every checkpoint a commit superseded in the thread's history, newest first in history and readable by id with checkpoint, until prune, a commit's retractTurn or deleteThread removes it - but keep pending writes for the latest checkpoint only;
  • number a thread's events 1, 2, 3, ... in commit order, inside the commit, never reusing a number - including after compaction, pruning or a failed commit;
  • keep events until compactEvents or prune removes them, and report the earliest sequence still available when asked to replay from before it (GraphError.ReplayUnavailable);
  • store checkpoints and pending writes as data (Checkpoint.toJson, PendingWrite's ReadWriter), so nothing executable survives a round trip;
  • return from awaitEventsAfter with what eventsAfter would, at once if the log already holds an event after afterSeq, and otherwise within about timeout - with the events of a commit made meanwhile through any store over the same storage, or empty;
  • tolerate the thread calling eventsAfter or awaitEventsAfter being interrupted at any point: cancelling a subscription interrupts its watch mid-read, so an interrupt must end that one call - with Left(CancelledError) or a failed result - and leave the store usable by every other thread and later call (see awaitEventsAfter).

The holder of a claim may commit and renew it after expiresAt for as long as no other claim has replaced it: expiry only lets another run take the thread over. CheckpointerContract in llm4s-agent-testkit is the executable form of this contract; a store should pass it.

Attributes

Companion
object
Supertypes
class Object
trait Matchable
class Any
Known subtypes
object Checkpointer

Attributes

Companion
trait
Supertypes
class Object
trait Matchable
class Any
Self type
final case class ClaimPolicy

How a GraphRuntime holds its runs' claims: each claim lasts ttl from when the store grants or renews it, and a running run renews it every renewEvery, on a virtual thread named llm4s-claim-<threadId>, until the run ends and releases it. A process that dies stops renewing, so after at most ttl its threads can be recovered elsewhere; a live run that cannot reach its store for longer than ttl can lose its claim the same way, after which its commits are refused (GraphError.StaleClaim) and it fails with GraphError.CheckpointWriteFailed.

How a GraphRuntime holds its runs' claims: each claim lasts ttl from when the store grants or renews it, and a running run renews it every renewEvery, on a virtual thread named llm4s-claim-<threadId>, until the run ends and releases it. A process that dies stops renewing, so after at most ttl its threads can be recovered elsewhere; a live run that cannot reach its store for longer than ttl can lose its claim the same way, after which its commits are refused (GraphError.StaleClaim) and it fails with GraphError.CheckpointWriteFailed.

Both must be positive and renewEvery shorter than ttl: apply and the with* setters throw IllegalArgumentException otherwise, and ClaimPolicy.of returns a ValidationError.

Attributes

Companion
object
Supertypes
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
object ClaimPolicy

Attributes

Companion
class
Supertypes
trait Product
trait Mirror
class Object
trait Matchable
class Any
Self type
final case class ClaimRequest

What a run asks of Checkpointer.claim: who holds the claim, and for how long it lasts from the moment the store grants it, by the store's clock. apply and the with* setters throw IllegalArgumentException for a non-positive ttl; ClaimRequest.of returns it as a ValidationError.

What a run asks of Checkpointer.claim: who holds the claim, and for how long it lasts from the moment the store grants it, by the store's clock. apply and the with* setters throw IllegalArgumentException for a non-positive ttl; ClaimRequest.of returns it as a ValidationError.

Attributes

Companion
object
Supertypes
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
object ClaimRequest

Attributes

Companion
class
Supertypes
trait Product
trait Mirror
class Object
trait Matchable
class Any
Self type
final case class Command(update: StateUpdate, routes: List[Route])

A node's state update and routes. Static edges declared on the builder are additive: they are scheduled before the command's routes. A command with no routes and no outgoing edges ends that branch; the run completes when no branch has work left.

A node's state update and routes. Static edges declared on the builder are additive: they are scheduled before the command's routes. A command with no routes and no outgoing edges ends that branch; the run completes when no branch has work left.

Attributes

Companion
object
Supertypes
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
object Command

Attributes

Companion
class
Supertypes
trait Product
trait Mirror
class Object
trait Matchable
class Any
Self type
Command.type
final case class Commit

One atomic write to a thread, fenced by the writing run's claim. The checkpointer applies all of it or none of it:

One atomic write to a thread, fenced by the writing run's claim. The checkpointer applies all of it or none of it:

  • token must be the FencingToken of the thread's current claim (GraphError.StaleClaim otherwise, checked first): a writer that lost its claim records nothing.
  • checkpoint, if present, becomes the thread's latest, provided its parent is the current latest - the thread version the writer expects (GraphError.CheckpointConflict) - and its id is not already in the thread's history (GraphError.InvalidCommit); the previous latest stays in the history, and the pending writes recorded against it are dropped.
  • pendingWrites are recorded against the (resulting) latest checkpoint, and must name it - the version they expect (GraphError.InvalidCommit).
  • events are appended to the thread's durable log, each given the next sequence number.
  • retractTurn, which needs a checkpoint (GraphError.InvalidCommit otherwise), first removes from the history every checkpoint after the thread's latest settled one - the newest whose status is Completed or Failed, or all of them if there is none - so that nothing of a turn a guardrail blocked stays readable. The runtime sets it on the Failed checkpoint that closes a run a node blocked (NodeResult.Block).

Attributes

Companion
object
Supertypes
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
object Commit

Attributes

Companion
class
Supertypes
trait Product
trait Mirror
class Object
trait Matchable
class Any
Self type
Commit.type
final class CompiledGraph[I, O]

An immutable, validated graph, run in supersteps.

An immutable, validated graph, run in supersteps.

Each superstep runs every ready task against the same committed ThreadState, then commits their updates and schedules the next frontier together:

  1. Tasks run in frontier order (possibly concurrently); none sees another's writes.
  2. If any task fails, the superstep commits nothing and the run fails with the first failure in frontier order.
  3. Each command is checked: every update is to a key in the node's declared write set, every route targets a node and join of this graph, and a task fans out to a join at most once.
  4. Updates apply task by task in frontier order, and in emission order within a task.
  5. The next frontier is, for each task in order, its static edges (declaration order) then its routes (route order, fan-out payloads in item order); then the targets of joins this commit released - static joins in declaration order, then dynamic activations in the order they opened.

A task that returns NodeResult.Suspend parks a continuation; its update commits with the superstep, and the run pauses after that superstep (RunResult.Suspended). A continuation stands in for the suspended task: when it completes it makes that task's join arrivals. The suspended task itself makes no arrival and fires none of its node's static edges.

A run's static breakpoints (RunConfig.interruptBefore, RunConfig.interruptAfter) park a task the same way: before its node runs, it is parked instead of run; after it ran, its update commits and its routes, static edges and join arrivals wait in its continuation. Either way the run pauses after the superstep, and the task's interrupt is answered with Breakpoint.proceed.

When the frontier is empty the run completes - unless a join is still waiting. A join waiting only for arrivals that parked continuations can make keeps the run suspended; a join waiting for an arrival nothing can make fails the run with GraphError.UnsatisfiedJoin.

Attributes

Supertypes
class Object
trait Matchable
class Any

Why a subscription ended with StreamEvent.Disconnected.

Why a subscription ended with StreamEvent.Disconnected.

Attributes

Supertypes
trait Enum
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
enum Durability

When a run's checkpoints and events become durable. In every mode a durable event is delivered only after the commit that numbered it, so no subscriber sees a sequence number that a crash could later reuse. In every mode a run claims its thread with a synchronous commit before it runs anything, and makes everything durable before it returns - so a returned RunResult.Suspended has been persisted and can be resumed by another process.

When a run's checkpoints and events become durable. In every mode a durable event is delivered only after the commit that numbered it, so no subscriber sees a sequence number that a crash could later reuse. In every mode a run claims its thread with a synchronous commit before it runs anything, and makes everything durable before it returns - so a returned RunResult.Suspended has been persisted and can be resumed by another process.

Attributes

Supertypes
trait Enum
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
final class DynamicJoin

A barrier attached to a fan-out. A Route.FanOut opens an activation recording the task id of every child it schedules; target is scheduled once all of them have completed. An empty fan-out releases immediately.

A barrier attached to a fan-out. A Route.FanOut opens an activation recording the task id of every child it schedules; target is scheduled once all of them have completed. An empty fan-out releases immediately.

Attributes

Supertypes
class Object
trait Matchable
class Any

A state operation as data: updates are encoded with the key's update codec.

A state operation as data: updates are encoded with the key's update codec.

Attributes

Supertypes
trait Enum
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all

A route as data: payloads are encoded with the target node's input codec.

A route as data: payloads are encoded with the target node's input codec.

Attributes

Supertypes
trait Enum
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
final case class EncodedSuspension(resumeNode: String, question: VersionedJson)

A suspended task's parked continuation: where it resumes and the question, as data.

A suspended task's parked continuation: where it resumes and the question, as data.

Attributes

Supertypes
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
final case class EventDraft(runId: String, checkpointId: Option[String], taskId: Option[String], nodeId: Option[String], timestamp: Instant, event: RunEvent)

A durable event before its commit assigns it a sequence number.

A durable event before its commit assigns it a sequence number.

Attributes

Supertypes
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
final case class EventRecord(threadId: String, seq: Long, runId: String, checkpointId: Option[String], taskId: Option[String], nodeId: Option[String], timestamp: Instant, event: RunEvent)

A committed durable event. seq is per thread, allocated in the commit that stored the event, contiguous and never reused; an event is delivered to subscribers only after that commit.

A committed durable event. seq is per thread, allocated in the commit that stored the event, contiguous and never reused; an event is delivered to subscribers only after that commit.

Attributes

Companion
object
Supertypes
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
object EventRecord

Attributes

Companion
class
Supertypes
trait Product
trait Mirror
class Object
trait Matchable
class Any
Self type
final class EventType[A]

A typed event: a payload type A with a stable name and version, sent durably with emit (a RunEvent.Custom, committed with the task) or live with progress (a StreamEvent.Live), and matched on either with unapply:

A typed event: a payload type A with a stable name and version, sent durably with emit (a RunEvent.Custom, committed with the task) or live with progress (a StreamEvent.Live), and matched on either with unapply:

val Ping = EventType[Ping]("my.ping", 1)
runtime.subscribe(threadId) {
 case Ping(p) => println(p)
 case _       => ()
}

unapply is None for another name or version, for a kernel event, and for a payload that does not decode (logged at DEBUG), so a listener never throws on an event it does not know.

Attributes

Companion
object
Supertypes
class Object
trait Matchable
class Any
object EventType

Attributes

Companion
class
Supertypes
class Object
trait Matchable
class Any
Self type
EventType.type
final class Execution

A graph run paused at a superstep boundary: the committed state, the ready frontier, the open join activations and any parked continuations. Advance it with CompiledGraph.step; answer its interrupts with CompiledGraph.resume; persist it with CompiledGraph.snapshot.

A graph run paused at a superstep boundary: the committed state, the ready frontier, the open join activations and any parked continuations. Advance it with CompiledGraph.step; answer its interrupts with CompiledGraph.resume; persist it with CompiledGraph.snapshot.

Attributes

Supertypes
class Object
trait Matchable
class Any
object FencingToken

Attributes

Supertypes
class Object
trait Matchable
class Any
Self type
final class GraphBuilder

Builds a typed graph. The builder issues every handle - nodes, joins - and validates the whole graph in compile, reporting every problem at once.

Builds a typed graph. The builder issues every handle - nodes, joins - and validates the whole graph in compile, reporting every problem at once.

Nodes that route to each other in a cycle are declared first and implemented afterwards:

val b      = GraphBuilder("counter", "v1")
val count  = StateKey.replace[Int]("count", 0)
val tick   = b.declare[Unit]("tick")
b.implement(tick, writes = Set(count)) { (_, state, _) =>
 NodeResult.fromResult(state.get(count).map { n =>
   val next = Command.empty.update(count, n + 1)
   if n + 1 < 3 then next.goto(tick) else next
 })
}
val graph = b.compile(tick)(_.get(count))

The builder is mutable and meant to be used from one thread while the graph is assembled; the CompiledGraph it produces is immutable.

Attributes

Companion
object
Supertypes
class Object
trait Matchable
class Any
object GraphBuilder

Attributes

Companion
class
Supertypes
class Object
trait Matchable
class Any
Self type
sealed trait GraphError extends LLMError

Errors raised while building, running or restoring a typed graph. Every case is a NonRecoverableError except GraphError.DeadlineExceeded: recover with a new budget continues that run.

Errors raised while building, running or restoring a typed graph. Every case is a NonRecoverableError except GraphError.DeadlineExceeded: recover with a new budget continues that run.

Attributes

Companion
object
Supertypes
trait LLMError
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
Known subtypes
object GraphError

Attributes

Companion
trait
Supertypes
trait Sum
trait Mirror
class Object
trait Matchable
class Any
Self type
GraphError.type
trait GraphNode[I]

A node's behaviour. It reads the superstep's committed snapshot - never another task's uncommitted writes - and returns its effects as data.

A node's behaviour. It reads the superstep's committed snapshot - never another task's uncommitted writes - and returns its effects as data.

Attributes

Supertypes
class Object
trait Matchable
class Any
object GraphRuntime

Runs compiled graphs on durable threads; see GraphRuntime.

Runs compiled graphs on durable threads; see GraphRuntime.

Attributes

Companion
class
Supertypes
class Object
trait Matchable
class Any
Self type
final class GraphRuntime(checkpointer: Checkpointer, clock: Clock, claims: ClaimPolicy, watch: WatchPolicy)

Runs compiled graphs on durable threads.

Runs compiled graphs on durable threads.

A thread's latest checkpoint says what may happen next:

  • none, Completed or Failed: start runs the graph with a new input (on a finished thread, over its committed state). Failed is a run that ended in a failure that is its outcome, not an interruption: a node returned NodeResult.Block, as a guardrail does. The thread is usable and recover has nothing to continue;
  • Running - work was scheduled when the last run stopped: recover continues it with no new input, reusing every pending write so completed tasks are not run again, and running failed or unstarted tasks again, each with its node's full RetryPolicy;
  • Suspended: resume answers any non-empty subset of the parked interrupts; unanswered ones stay parked, and the run suspends again if nothing else can proceed.

Each call's RunConfig brings the run's static breakpoints; one on a node the graph does not have is refused with a ValidationError before the thread is read. A task they hold parks like a task that suspended, so the thread ends Suspended and resume answers it with Breakpoint.proceed.

Any other call is refused (GraphError.IncompleteRun, GraphError.PendingInterrupts, GraphError.NothingToRecover, GraphError.NotSuspended) without changing the thread. A thread belongs to the tenant on its latest checkpoint, and a call with another tenantId is refused with GraphError.TenantMismatch before anything else is reported - the thread's status, or that a run is live on it - and the error names only the caller's tenant, so it learns nothing about the thread.

Each call is a new run, and claims the thread in two steps before it runs anything. First it asks the store for a RunClaim: a lease with an expiry and a FencingToken, which the run renews while it executes (see ClaimPolicy) and releases when it ends. While another run's claim is live - in this runtime or in any other runtime or process sharing the store - the call fails with GraphError.ThreadBusy naming that run, so recover elsewhere refuses a live run and takes over a dead one only once its claim has expired. Then it commits a checkpoint whose parent is the latest it read; if another run advanced the thread in between, it fails with ThreadBusy too. Either way its input or answers are neither accepted nor discarded. Every commit of the run carries its claim's token, and the store refuses one whose claim was taken over (GraphError.StaleClaim), so a run that lost its claim - a process paused past ttl - cannot record anything after its successor started: it fails with GraphError.CheckpointWriteFailed. A call on a thread whose run is still executing in this runtime fails with ThreadBusy before reading the thread at all.

Admission - the checks above, restoring the thread and committing the claim - runs on the caller's thread and never throws: a Left means no run exists, and the thread is free again. A throwable from the store, the clock or the graph during admission is GraphError.RunCrashed, and an interrupt is CancelledError with the flag set. The run itself executes on a virtual thread owned by the runtime, named llm4s-run-<threadId>, behind the returned RunHandle; the thread stays busy until that run thread exits. An unexpected throwable escaping the run ends it with GraphError.RunCrashed.

RunHandle.cancel cancels the run by interrupting its run thread: every task is interrupted and joined, tasks that finished first keep their pending writes, an interrupted task records nothing, and the run ends Failed with GraphError.Cancelled - naming the last checkpoint, which a RunEvent.RunCancelled event is committed against. The checkpoint stays Running, so recover continues the run. A cancel that interrupts a superstep's commit ends the run the same way even if the store reports that commit as failed (as a JDBC store may, rather than throwing InterruptedException): the run is cancelled, not failed by its store, and the error names the last checkpoint that was durable. Once the run has begun committing its outcome - its completed or suspended checkpoint, or the RunFailed of a failed run - a cancel is ignored - it sends no interrupt, so that commit is not disturbed - and the run ends with its outcome. Interrupting a thread blocked in RunHandle.await does not cancel the run.

A run whose RunBudgets.timeout is set has a deadline, fixed when its claim commits. When it passes, the run stops the same way, but ends with GraphError.DeadlineExceeded and commits RunEvent.RunTimedOut. The first of cancel and expiry to be recorded wins, so a run reports exactly one. DeadlineExceeded is recoverable: recover with a new budget continues the run.

subscribe replays a thread's committed events after a sequence number and then delivers new ones as their commits succeed, in ascending order with no gaps or duplicates, followed by live progress as it happens. Each subscription has its own dispatcher thread and a queue of capacity events, so a slow listener never holds up a run: one that falls behind by more than capacity durable events is disconnected (DisconnectReason.Lagging), and live events that do not fit are dropped and counted (StreamEvent.LiveGap). See EventHub. Live events are never replayed, but a subscription receives every one sent after subscribe returns, also while it is still replaying: so subscribing and then calling start loses none of the run's. One made after start returns can miss the run's first live events; an Observer passed to start, recover or resume is subscribed during admission, before the claim commits, and so sees every event of the run (RunHandle.observation).

A subscription also sees the durable events of commits made through another runtime or process sharing the checkpointer, in the same order and with the same guarantees: each live subscription watches the store (WatchPolicy, Checkpointer.awaitEventsAfter), so they arrive as soon as the store reports them - at once from a store that is told of commits, within pollInterval from one that is polled. Live progress events are never stored, so another runtime's do not arrive.

Attributes

Companion
object
Supertypes
class Object
trait Matchable
class Any
final case class GraphSnapshot(graphId: String, graphVersion: String, fingerprint: String, superstep: Int, state: Map[String, VersionedJson], frontier: Vector[PendingTask], staticJoins: Vector[StaticArrivals], dynamicJoins: Vector[Activation], parked: Vector[ParkedContinuation], paused: Boolean)

A serializable picture of an Execution - data only, no closures or codecs. Node inputs, questions and state values are encoded with the codecs of the graph that wrote them, and decoded and checked against the graph that restores them.

A serializable picture of an Execution - data only, no closures or codecs. Node inputs, questions and state values are encoded with the codecs of the graph that wrote them, and decoded and checked against the graph that restores them.

Each value records its codec's version and is migrated on restore; the snapshot itself is versioned by the Checkpoint that carries it.

Attributes

Companion
object
Supertypes
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
object GraphSnapshot

Attributes

Companion
class
Supertypes
trait Product
trait Mirror
class Object
trait Matchable
class Any
Self type

Attributes

Supertypes
class Object
trait Matchable
class Any
Self type
final class InMemoryCheckpointer(clock: Clock) extends Checkpointer

A Checkpointer in memory. Checkpoints and pending writes are stored as JSON and decoded on read, exactly as a database-backed store would, so nothing executable survives a round trip. Claims expire, and prune judges age, by clock. Fencing tokens come from one counter for the whole store, so they never repeat for a thread, even after it is deleted. awaitEventsAfter wakes on the store's own commits, so every runtime sharing the instance sees a commit as soon as it lands, without polling.

A Checkpointer in memory. Checkpoints and pending writes are stored as JSON and decoded on read, exactly as a database-backed store would, so nothing executable survives a round trip. Claims expire, and prune judges age, by clock. Fencing tokens come from one counter for the whole store, so they never repeat for a thread, even after it is deleted. awaitEventsAfter wakes on the store's own commits, so every runtime sharing the instance sees a commit as soon as it lands, without polling.

Attributes

Supertypes
trait Checkpointer
class Object
trait Matchable
class Any
object InterruptId

Attributes

Supertypes
class Object
trait Matchable
class Any
Self type
object JoinId

Attributes

Supertypes
class Object
trait Matchable
class Any
Self type
JoinId.type
object NodeId

Attributes

Supertypes
class Object
trait Matchable
class Any
Self type
NodeId.type
final class NodeRef[I]

A handle to a node that consumes I, issued by a GraphBuilder.

A handle to a node that consumes I, issued by a GraphBuilder.

Handles are the only way to route: a node cannot name another by string. Goto takes a NodeRef[Unit] and Send a payload of the target's input type, so a mis-typed route does not compile. A handle from another builder is rejected when the graph compiles, or when a node returns it at run time.

Attributes

Supertypes
class Object
trait Matchable
class Any
enum NodeResult

What a node task produced.

What a node task produced.

Attributes

Companion
object
Supertypes
trait Enum
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
Known subtypes
class Suspend[Q, A]
object NodeResult

Attributes

Companion
enum
Supertypes
trait Sum
trait Mirror
class Object
trait Matchable
class Any
Self type
NodeResult.type
final case class Observer(capacity: Int, listener: StreamEvent => Unit)

A listener subscribed to a run's thread during admission - before the run's claim commits, with no replay - so it receives every durable event of the run from its claim, and every live event, of which a GraphRuntime.subscribe made after start returns can miss the first: a subscription receives only the live events sent after it returns. capacity is the subscription's queue size, at least 2, as for GraphRuntime.subscribe. The subscription is thread-scoped like any other: it keeps delivering later runs until cancelled, through RunHandle.observation. A refused admission abandons it, and its listener is never called.

A listener subscribed to a run's thread during admission - before the run's claim commits, with no replay - so it receives every durable event of the run from its claim, and every live event, of which a GraphRuntime.subscribe made after start returns can miss the first: a subscription receives only the live events sent after it returns. capacity is the subscription's queue size, at least 2, as for GraphRuntime.subscribe. The subscription is thread-scoped like any other: it keeps delivering later runs until cancelled, through RunHandle.observation. A refused admission abandons it, and its listener is never called.

Attributes

Supertypes
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
final case class PendingInterrupt(id: InterruptId, resumeNode: NodeId, question: Value, breakpoint: Option[BreakpointPhase])

A parked continuation, as reported by a suspended run. For a task a static breakpoint holds, breakpoint is its phase, resumeNode is the held task's own node, and question is the task's input before it ran, or JSON null after; answer it with Breakpoint.proceed.

A parked continuation, as reported by a suspended run. For a task a static breakpoint holds, breakpoint is its phase, resumeNode is the held task's own node, and question is the task's input before it ran, or JSON null after; answer it with Breakpoint.proceed.

Attributes

Supertypes
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
final case class PendingWrite(checkpointId: String, taskId: String, nodeId: String, operations: Vector[EncodedOperation], routes: Vector[EncodedRoute], suspension: Option[EncodedSuspension])

A completed (or suspended) task's result, recorded against the checkpoint whose frontier it ran in, before the superstep commits. On recovery the task is not run again: its command is decoded from here.

A completed (or suspended) task's result, recorded against the checkpoint whose frontier it ran in, before the superstep commits. On recovery the task is not run again: its command is decoded from here.

Attributes

Supertypes
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
object Principal

Attributes

Supertypes
class Object
trait Matchable
class Any
Self type
Principal.type
final class ResumeRef[Q, A]

A handle to a node that continues suspended work: it consumes Resumed[Q, A]. Issued by GraphBuilder.declareResume; a node may suspend only to a resume handle. The question and answer codecs belong to the graph - a checkpoint stores the question as JSON and a resume supplies the answer as JSON, and both are decoded here.

A handle to a node that continues suspended work: it consumes Resumed[Q, A]. Issued by GraphBuilder.declareResume; a node may suspend only to a resume handle. The question and answer codecs belong to the graph - a checkpoint stores the question as JSON and a resume supplies the answer as JSON, and both are decoded here.

Attributes

Supertypes
class Object
trait Matchable
class Any
final case class Resumed[Q, A](question: Q, answer: A)

A suspended task's question with the answer it was resumed with.

A suspended task's question with the answer it was resumed with.

Attributes

Supertypes
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
final case class RetentionPolicy

How much of a thread's history Checkpointer.prune keeps, by age or by size. Every limit is optional, and one that is not set removes nothing, so RetentionPolicy() keeps everything.

How much of a thread's history Checkpointer.prune keeps, by age or by size. Every limit is optional, and one that is not set removes nothing, so RetentionPolicy() keeps everything.

  • maxAge: a checkpoint created more than maxAge ago, and an event recorded more than maxAge ago, is removed - by the store's clock, against the checkpoint's createdAt and the event's timestamp.
  • maxCheckpoints: only the newest maxCheckpoints checkpoints are kept.
  • maxEvents: only the newest maxEvents events are kept.

Whatever the limits, the thread's latest checkpoint and its pending writes are never removed, so pruning never changes what start, recover or resume does next. Pruning a checkpoint also removes the events recorded before the oldest checkpoint kept; maxAge and maxEvents may remove more events than that, including the latest checkpoint's. Removing events raises the thread's replay floor exactly as Checkpointer.compactEvents does (GraphError.ReplayUnavailable).

apply and the with* setters throw IllegalArgumentException for a non-positive maxAge or maxCheckpoints, or a negative maxEvents; RetentionPolicy.of returns a ValidationError.

Attributes

Companion
object
Supertypes
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all

Attributes

Companion
class
Supertypes
trait Product
trait Mirror
class Object
trait Matchable
class Any
Self type
final case class RetryPolicy

How a node is run again after its own failure, inside the run.

How a node is run again after its own failure, inside the run.

A node that throws, or returns NodeResult.Fail, is run again against the same committed snapshot while its error passes retryOn and attempts remain. By default an error is retried by the library's one retry rule, org.llm4s.reliability.RetryPolicy.isRetryable: a recoverable error, except a client-error response and an optimistic-lock failure, which repeating the node cannot fix. A cancellation, a result the kernel rejects (an undeclared write, an invalid route) and a suspension are never retried.

The wait after the n-th failed attempt is initialBackoff * backoffFactor^(n-1), at most maxBackoff. It is an interruptible wait: cancelling the run, or its deadline expiring, ends the retries. The attempts belong to one run: recover runs a failed task again with its full policy.

Every value is validated on the way in: apply and the with* setters throw IllegalArgumentException; RetryPolicy.of returns a ValidationError for untrusted input.

Value parameters

backoffFactor

what each further wait is multiplied by; at least 1.0

initialBackoff

the wait after the first failed attempt

maxAttempts

the most times the node is run, the first included; 1 means no retry

maxBackoff

the longest wait

retryOn

whether an error is worth another attempt

Attributes

Companion
object
Supertypes
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
object RetryPolicy

Attributes

Companion
class
Supertypes
trait Product
trait Mirror
class Object
trait Matchable
class Any
Self type
enum Route

A routing decision returned by a node; scheduled for the next superstep.

A routing decision returned by a node; scheduled for the next superstep.

Attributes

Supertypes
trait Enum
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
Known subtypes
class Send[I]
class FanOut[I]
final case class RunBudgets

Limits on one run; each start, recover or resume brings its own. Every value is validated on the way in: apply and the with* setters throw IllegalArgumentException for a non-positive one, and RunBudgets.of returns it as a ValidationError.

Limits on one run; each start, recover or resume brings its own. Every value is validated on the way in: apply and the with* setters throw IllegalArgumentException for a non-positive one, and RunBudgets.of returns it as a ValidationError.

Attributes

Companion
object
Supertypes
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
object RunBudgets

Attributes

Companion
class
Supertypes
trait Product
trait Mirror
class Object
trait Matchable
class Any
Self type
RunBudgets.type
final case class RunClaim

A run's lease on a thread, as a Checkpointer granted it: the run that holds it, the FencingToken its commits must carry, and when it expires by the store's clock unless renewed. While it is live - expiresAt has not passed - no other claim on the thread is granted, so a run in another runtime or process is refused with GraphError.ThreadBusy. Once it has expired, another run may take the thread over, and the store then refuses this claim's token (GraphError.StaleClaim). Until then the holder may still commit and renew, even past expiresAt: expiry only lets another run claim the thread.

A run's lease on a thread, as a Checkpointer granted it: the run that holds it, the FencingToken its commits must carry, and when it expires by the store's clock unless renewed. While it is live - expiresAt has not passed - no other claim on the thread is granted, so a run in another runtime or process is refused with GraphError.ThreadBusy. Once it has expired, another run may take the thread over, and the store then refuses this claim's token (GraphError.StaleClaim). Until then the holder may still commit and renew, even past expiresAt: expiry only lets another run claim the thread.

Attributes

Companion
object
Supertypes
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
object RunClaim

Attributes

Companion
class
Supertypes
trait Product
trait Mirror
class Object
trait Matchable
class Any
Self type
RunClaim.type
final case class RunConfig

The identity and limits of one run. RunConfig() is evaluated per call, so each gets a fresh RunId. The tenant is part of the thread's identity: it is recorded on every checkpoint, and admission refuses a run whose tenantId differs from the latest checkpoint's (GraphError.TenantMismatch; None and Some differ). The principal is recorded on the run's RunStarted, RunRecovered and RunResumed events and is never checked.

The identity and limits of one run. RunConfig() is evaluated per call, so each gets a fresh RunId. The tenant is part of the thread's identity: it is recorded on every checkpoint, and admission refuses a run whose tenantId differs from the latest checkpoint's (GraphError.TenantMismatch; None and Some differ). The principal is recorded on the run's RunStarted, RunRecovered and RunResumed events and is never checked.

interruptBefore and interruptAfter are the run's static breakpoints (BreakpointPhase): a task of a node in interruptBefore is held before it runs, and one of a node in interruptAfter after it ran, each as an interrupt of its own that GraphRuntime.resume answers with Breakpoint.proceed. They belong to the run, like its budgets: a resume or recover brings its own, and a continuation already past a breakpoint is not held by it again. Admission refuses a node the graph does not have with a ValidationError.

Attributes

Companion
object
Supertypes
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
object RunConfig

Attributes

Companion
class
Supertypes
trait Product
trait Mirror
class Object
trait Matchable
class Any
Self type
RunConfig.type
final class RunContext

What a running task knows: the run's RunConfig, its own RunPosition, and its event channels.

What a running task knows: the run's RunConfig, its own RunPosition, and its event channels.

emit records a durable custom event: it is committed with this task's result, given a per-thread sequence number in that commit, delivered only after the commit and replayed to later subscribers. It is discarded if the task fails. progress is live-only, for token deltas and similar high-volume progress, and carries a name and version like emit: delivered at once to current subscribers, never persisted or replayed. Outside a GraphRuntime both are no-ops.

Attributes

Supertypes
class Object
trait Matchable
class Any
enum RunEvent

What happened in a run. Durable: persisted in the thread's event log and replayable.

What happened in a run. Durable: persisted in the thread's event log and replayable.

The three events that begin a run record the run's tenantId and principal (as supplied in its RunConfig); the log reads events written before they existed as having neither.

Attributes

Supertypes
trait Enum
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
trait RunHandle[O]

A run admitted by GraphRuntime.start, GraphRuntime.recover or GraphRuntime.resume. Its thread was claimed before the handle was returned, and the run executes on a virtual thread owned by the runtime, named llm4s-run-<threadId>, which holds the thread until it exits.

A run admitted by GraphRuntime.start, GraphRuntime.recover or GraphRuntime.resume. Its thread was claimed before the handle was returned, and the run executes on a virtual thread owned by the runtime, named llm4s-run-<threadId>, which holds the thread until it exits.

Attributes

Supertypes
class Object
trait Matchable
class Any
object RunId

Attributes

Supertypes
class Object
trait Matchable
class Any
Self type
RunId.type
final case class RunPosition

Where a task runs. checkpointId is the checkpoint whose frontier it belongs to; "" outside a GraphRuntime. fencingToken is the token of the run's claim on the thread (RunClaim), None outside a runtime: a node that writes to an external system able to fence can pass it on, so that system too refuses a run that has lost its claim.

Where a task runs. checkpointId is the checkpoint whose frontier it belongs to; "" outside a GraphRuntime. fencingToken is the token of the run's claim on the thread (RunClaim), None outside a runtime: a node that writes to an external system able to fence can pass it on, so that system too refuses a run that has lost its claim.

Attributes

Companion
object
Supertypes
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
object RunPosition

Attributes

Companion
class
Supertypes
trait Product
trait Mirror
class Object
trait Matchable
class Any
Self type
enum RunResult[+O]

The outcome of a run.

The outcome of a run.

Attributes

Supertypes
trait Enum
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
Known subtypes
class Completed[O]
class Suspended
class Failed
enum RunStatus

Where a run is; see RunHandle.status.

Where a run is; see RunHandle.status.

Attributes

Supertypes
trait Enum
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
final class SchemaVersion

The current version of a persisted JSON shape, with the migrations that bring older versions up to it. A state key's value, a state key's update and a node's input each carry one; their stable codec id is the owner's id with this version (<keyId>@<version>), and every encoded value records the version it was written with (see VersionedJson).

The current version of a persisted JSON shape, with the migrations that bring older versions up to it. A state key's value, a state key's update and a node's input each carry one; their stable codec id is the owner's id with this version (<keyId>@<version>), and every encoded value records the version it was written with (see VersionedJson).

A step keyed n migrates JSON written at version n to version n + 1. Steps are plain functions of the compiled graph, never persisted.

Attributes

Companion
object
Supertypes
class Object
trait Matchable
class Any
object SchemaVersion

Attributes

Companion
class
Supertypes
class Object
trait Matchable
class Any
Self type
final class StateKey[A, U]

A typed slot in a graph's thread state.

A typed slot in a graph's thread state.

A is the stored value and U the update a node emits for it. Every update - including a single writer's - is applied to the committed value with applyUpdate, in deterministic task and emission order; replacement is the special case U = A (see StateKey.replace). The function belongs to the compiled graph, never to a checkpoint: checkpoints hold values encoded with stateCodec and pending updates encoded with updateCodec, each tagged with the codec's SchemaVersion so an older checkpoint is migrated before it is decoded.

Keys are compared by identity. A graph rejects two distinct keys with the same id.

Attributes

Companion
object
Supertypes
class Object
trait Matchable
class Any
object StateKey

Attributes

Companion
class
Supertypes
class Object
trait Matchable
class Any
Self type
StateKey.type
object StateKeyId

Attributes

Supertypes
class Object
trait Matchable
class Any
Self type
StateKeyId.type
final class StateUpdate

An ordered list of state operations emitted by one node task.

An ordered list of state operations emitted by one node task.

Operations apply in emission order. combine is sequential composition: a.combine(b) applies a's operations and then b's, so for a StateKey.replace key the later value wins and for an operation-valued key both operations apply. Updates from different tasks in one superstep are never combined; the scheduler applies them task by task in frontier order.

Attributes

Companion
object
Supertypes
class Object
trait Matchable
class Any
object StateUpdate

Attributes

Companion
class
Supertypes
class Object
trait Matchable
class Any
Self type
final class StaticJoin

A barrier that schedules target once every source node has completed a task since its last release. Each source counts once per activation, however many of its tasks complete.

A barrier that schedules target once every source node has completed a task since its last release. Each source counts once per activation, however many of its tasks complete.

Attributes

Supertypes
class Object
trait Matchable
class Any
enum Step[+O]

The outcome of one superstep.

The outcome of one superstep.

Attributes

Supertypes
trait Enum
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
Known subtypes
class Next
class Done[O]
final case class StoredCheckpoint(checkpoint: Checkpoint, pendingWrites: Vector[PendingWrite])

A thread's latest checkpoint with the pending writes recorded against it.

A thread's latest checkpoint with the pending writes recorded against it.

Attributes

Supertypes
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all

What a subscriber receives. A payload - of a StreamEvent.Live or a RunEvent.Custom - is a snapshot taken when the node emitted it, and one value may be shared by every subscriber: a listener must not mutate it, and copies it (ujson.copy) to change it.

What a subscriber receives. A payload - of a StreamEvent.Live or a RunEvent.Custom - is a snapshot taken when the node emitted it, and one value may be shared by every subscriber: a listener must not mutate it, and copies it (ujson.copy) to change it.

Attributes

Supertypes
trait Enum
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
trait Subscription

A registration with GraphRuntime.subscribe or RunHandle.subscribe. It is scoped to a thread, not a run: it keeps delivering the events of every later run on the same thread, and its dispatcher - a virtual thread, parked while there is nothing to deliver - lives until cancel is called or the subscription is disconnected. Cancel every subscription you no longer need.

A registration with GraphRuntime.subscribe or RunHandle.subscribe. It is scoped to a thread, not a run: it keeps delivering the events of every later run on the same thread, and its dispatcher - a virtual thread, parked while there is nothing to deliver - lives until cancel is called or the subscription is disconnected. Cancel every subscription you no longer need.

It delivers the durable events of every commit on the thread, made through the GraphRuntime it was made on or through any other runtime or process sharing the same Checkpointer: the latter it reads from the store as they land (WatchPolicy). Live progress events reach it only from runs of its own runtime, because they are never stored.

Attributes

Supertypes
class Object
trait Matchable
class Any
object TaskId

Attributes

Supertypes
class Object
trait Matchable
class Any
Self type
TaskId.type
object TenantId

Attributes

Supertypes
class Object
trait Matchable
class Any
Self type
TenantId.type
object ThreadId

Attributes

Supertypes
class Object
trait Matchable
class Any
Self type
ThreadId.type
final class ThreadState

The committed state of a graph thread: a typed key/value store over the graph's registered StateKeys. It is immutable, so every task in a superstep reads the same snapshot.

The committed state of a graph thread: a typed key/value store over the graph's registered StateKeys. It is immutable, so every task in a superstep reads the same snapshot.

Reads are checked: a key the graph did not register - or a different key instance sharing a registered key's id - is an GraphError.UnknownStateKey. A registered key with no stored entry reads as its initial value. The erasure to Any stays private to this boundary.

Attributes

Supertypes
class Object
trait Matchable
class Any
object ToolCallId

Attributes

Supertypes
class Object
trait Matchable
class Any
Self type
ToolCallId.type
object ToolName

Attributes

Supertypes
class Object
trait Matchable
class Any
Self type
ToolName.type

Bridges a thread's durable run events to a org.llm4s.trace.Tracing: each becomes a TraceEvent.CustomEvent named graph.<event> (RunStarted is graph.run_started), stamped with the record's timestamp. Its data holds threadId, runId, seq, checkpointId, taskId and nodeId (null when absent) and the event's own fields. Live progress is not traced.

Bridges a thread's durable run events to a org.llm4s.trace.Tracing: each becomes a TraceEvent.CustomEvent named graph.<event> (RunStarted is graph.run_started), stamped with the record's timestamp. Its data holds threadId, runId, seq, checkpointId, taskId and nodeId (null when absent) and the event's own fields. Live progress is not traced.

A subscription that falls behind is disconnected like any other: a StreamEvent.Disconnected(lastSeq, DisconnectReason.Lagging) ends tracing, and is only logged. Nothing re-attaches by itself: to keep tracing, the caller attaches again with afterSeq = lastSeq, which replays from the first event not traced.

Attach it to any graph's thread, kernel graphs included. An Agent built withTracing traces through AgentTracing instead, which adds usage and AgentRunEnded; use attach for graphs of your own.

Attributes

Supertypes
class Object
trait Matchable
class Any
Self type
final case class VersionedJson(version: Int, value: Value)

A persisted value and the version of the codec that wrote it.

A persisted value and the version of the codec that wrote it.

Attributes

Supertypes
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
final case class WatchPolicy

How a GraphRuntime's subscriptions learn of commits made through another runtime or process sharing its Checkpointer. Commits made through the runtime itself are handed to its subscriptions as they land, whatever this says.

How a GraphRuntime's subscriptions learn of commits made through another runtime or process sharing its Checkpointer. Commits made through the runtime itself are handed to its subscriptions as they land, whatever this says.

While enabled, each live subscription watches the store on a virtual thread of its own, named llm4s-watch-<threadId>, calling Checkpointer.awaitEventsAfter with pollInterval as the timeout, from the last event it has queued. A store that can be told of commits returns as soon as one lands; one that cannot - the default, and the SQLite store - is read once per pollInterval, so a commit made elsewhere reaches the subscription up to pollInterval after it lands. Only durable events cross runtimes: live progress (StreamEvent.Live) is never stored, so it reaches only the subscriptions of the runtime whose run sent it. When disabled, a subscription sees another runtime's commits only by subscribing again, which replays the log; a runtime that knows it is the only one using its store can disable it to save the watching thread and its reads.

pollInterval must be at least one millisecond - a shorter one would have every subscription read a polled store in a busy loop: apply and the with* setters throw IllegalArgumentException otherwise, and WatchPolicy.of returns a ValidationError.

Attributes

Companion
object
Supertypes
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
object WatchPolicy

Attributes

Companion
class
Supertypes
trait Product
trait Mirror
class Object
trait Matchable
class Any
Self type

Types

opaque type FencingToken

The fencing token of a run's claim on a thread (RunClaim). A Checkpointer issues one with every claim, strictly greater than every token it issued for that thread before - including before a takeover, a release or a deleteThread - and accepts a commit only with the token of the thread's current claim, so a writer that lost its claim cannot commit after another took over.

The fencing token of a run's claim on a thread (RunClaim). A Checkpointer issues one with every claim, strictly greater than every token it issued for that thread before - including before a takeover, a release or a deleteThread - and accepts a commit only with the token of the thread's current claim, so a writer that lost its claim cannot commit after another took over.

Attributes

opaque type IdempotencyKey

The key a tool gives an external system so that a second run of the same tool call does not repeat its side effect: one key per model-issued call, the same in every run of that call (a retrying wrapper, an approval, an answered question, recover after a failure, a cancellation or a crash), and different for a call from another model request, even one that reuses the provider's call id.

The key a tool gives an external system so that a second run of the same tool call does not repeat its side effect: one key per model-issued call, the same in every run of that call (a retrying wrapper, an approval, an answered question, recover after a failure, a cancellation or a crash), and different for a call from another model request, even one that reuses the provider's call id.

The agent loop derives it with IdempotencyKey.derive from where on the thread the model call that issued the call ran - its checkpoint, superstep and task - and the call's id, and records it with the call, so it reaches the tool as ToolContext.idempotencyKey. It de-duplicates only where the external system honours it: the runtime runs a tool at least once, never exactly once (design ยง4.1).

Attributes

opaque type InterruptId

Identifies a parked continuation awaiting an answer; stable across processes.

Identifies a parked continuation awaiting an answer; stable across processes.

Attributes

opaque type JoinId

Stable identifier of a static or dynamic join barrier; persisted in snapshots.

Stable identifier of a static or dynamic join barrier; persisted in snapshots.

Attributes

opaque type NodeId

Stable identifier of a node in a compiled graph; persisted in snapshots.

Stable identifier of a node in a compiled graph; persisted in snapshots.

Attributes

opaque type Principal

Who a run acts for.

Who a run acts for.

Attributes

opaque type RunId

One execution attempt on a thread; start, recover and (later) resume each begin a new run.

One execution attempt on a thread; start, recover and (later) resume each begin a new run.

Attributes

opaque type StateKeyId

Stable identifier of a StateKey; persisted in snapshots.

Stable identifier of a StateKey; persisted in snapshots.

Attributes

opaque type TaskId

Identifier of one scheduled node execution; unique within a thread's history.

Identifier of one scheduled node execution; unique within a thread's history.

Attributes

opaque type TenantId

The tenant a thread belongs to.

The tenant a thread belongs to.

Attributes

opaque type ThreadId

A conversation or workflow thread: the address of its checkpoints and event log.

A conversation or workflow thread: the address of its checkpoints and event log.

Attributes

opaque type ToolCallId

The provider's identifier of one tool call; unique within a conversation.

The provider's identifier of one tool call; unique within a conversation.

Attributes

opaque type ToolName

The name of a tool, as the model calls it.

The name of a tool, as the model calls it.

Attributes