Class FlowContext

java.lang.Object
dyntabs.ai.flow.FlowContext

public final class FlowContext extends Object
The typed value-bag that travels through an EasyAI.flow() pipeline, carrying the flow's original input and the result of every step that has run so far, each keyed by its step name.

This is the heart of the flow() idea: instead of the LLM holding the whole task in its head and improvising, the state of the process lives in a plain, typed Java object that you can read, assert on, and log. Each step reads what earlier steps produced (get(String, Class)), does its work, and its return value is clipped in under its own name for the steps that follow.

Familiar analogy: the job folder that slides down an assembly line. It starts with the order form (input()), and each station reads the notes clipped in by earlier stations and clips in its own before passing it on. At the end you hold the whole folder — every note in the order it was added (trail()), plus the last one (result()).

Immutability & testability

A FlowContext is an immutable snapshot: Flow.run(Object) builds a fresh one before each step, holding the results accumulated up to that point. Steps never mutate it — they return a value and the flow records it. This snapshot design is also what makes a step testable in isolation: construct a FlowContext yourself with a canned prior result and pass it straight into your FlowStep — no running flow required.


 // Testing a step in isolation, no live LLM:
 FlowContext ctx = new FlowContext(
         "order 3 blue watches",
         Map.of("understand", new OrderRequest("watch", 3, "blue")));
 String txn = payStep.run(ctx);         // reads ctx.get("understand", OrderRequest.class)
 assertEquals("txn-…", txn);
 

Place in the flow

   Flow.run(input)
        → new FlowContext(input, results-so-far)   // rebuilt before each step
        → passed into FlowStep.run(ctx)            // the step reads input()/get(name, type)
        → (final snapshot returned to the caller of Flow.run)
 
See Also:
  • Constructor Summary

    Constructors
    Constructor
    Description
    FlowContext(Object input, Map<String,Object> results)
    Builds an immutable context from the flow's input and the results gathered so far.
  • Method Summary

    Modifier and Type
    Method
    Description
    <T> T
    get(String name, Class<T> type)
    Returns the result an earlier step produced, cast to the requested type.
    boolean
    has(String name)
    Tells whether a given step has already produced a result in this context.
    Returns the flow's original input, untyped.
    <T> T
    input(Class<T> type)
    Returns the flow's original input, cast to the requested type.
    Convenience for the common case where the input is (or should be read as) text — e.g. the user's message the first LLM step needs to understand.
    Returns the most recently produced step result (the previous step's output when read mid-flow, or the final step's output on the snapshot returned by Flow.run).
    Returns an unmodifiable, insertion-ordered view of every step result gathered so far, keyed by step name.
    Renders a compact, human-readable trace of what has happened so far — one line per completed step, name → value, in order.

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Constructor Details

    • FlowContext

      public FlowContext(Object input, Map<String,Object> results)
      Builds an immutable context from the flow's input and the results gathered so far.

      Called by Flow.run(Object) before every step (with a growing result map), and again at the end to produce the snapshot handed back to the caller. Application code rarely constructs one directly — the main exception is unit tests, where building a context with a canned prior result lets you exercise a single FlowStep without a running flow.

      Parameters:
      input - the flow's original input (whatever was passed to Flow.run(...)); may be null
      results - prior step results keyed by step name; copied defensively, may be null or empty
  • Method Details

    • input

      public Object input()
      Returns the flow's original input, untyped.

      This is whatever you passed to Flow.run(...) — often the raw user text that the first ("understand") step feeds to the LLM. Use input(Class) when you want it typed.

      Returns:
      the original input, or null if the flow was run with null
    • input

      public <T> T input(Class<T> type)
      Returns the flow's original input, cast to the requested type.
      Type Parameters:
      T - the expected input type
      Parameters:
      type - the class to cast the input to
      Returns:
      the input as T
      Throws:
      ClassCastException - if the input is not an instance of type
    • inputText

      public String inputText()
      Convenience for the common case where the input is (or should be read as) text — e.g. the user's message the first LLM step needs to understand.
      Returns:
      the input rendered as a string, or null if the input is null
    • get

      public <T> T get(String name, Class<T> type)
      Returns the result an earlier step produced, cast to the requested type.

      This is how a step reads what came before it — ctx.get("understand", OrderRequest.class) in a pay step, for instance. The name is the exact step name you registered with FlowBuilder.step(name, ...).

      Type Parameters:
      T - the expected result type
      Parameters:
      name - the step name whose result you want
      type - the class to cast that result to
      Returns:
      the named step's result as T
      Throws:
      IllegalArgumentException - if no step named name has run (yet)
      ClassCastException - if that step's result is not an instance of type
    • has

      public boolean has(String name)
      Tells whether a given step has already produced a result in this context.
      Parameters:
      name - the step name to check
      Returns:
      true if a step named name has run and stored a result
    • result

      public Object result()
      Returns the most recently produced step result (the previous step's output when read mid-flow, or the final step's output on the snapshot returned by Flow.run).
      Returns:
      the last stored result, or null if no step has produced one yet
    • results

      public Map<String,Object> results()
      Returns an unmodifiable, insertion-ordered view of every step result gathered so far, keyed by step name.
      Returns:
      the step results in the order they were produced (never null)
    • trail

      public String trail()
      Renders a compact, human-readable trace of what has happened so far — one line per completed step, name → value, in order.

      Handy for two things: feeding a final "summarize" LLM step (EasyAI.chat().build().send("Tell the user what happened:\n" + ctx.trail())) and plain logging/auditing of the run.

      Returns:
      a newline-separated name → value trace (empty string if nothing has run yet)