Smithers - Declarative AI Orchestration with React

(github.com)

2 points | by roninjin10 2 hours ago

1 comments

  • roninjin10 2 hours ago
    I built Smithers to make long-running AI workflows deterministic, resumable, and observable.

    <Ralph until={ctx.latest("review","r")?.approved} maxIterations={3}>

      <Task id="impl" output="impl" agent={coder}>Implement</Task>
    
      <Task id="test" output="test" agent={ci}>Run tests</Task>
    
      <Task id="r" output="review" agent={reviewer}>Review</Task>
    
    </Ralph>

    The model is “plan mode as code”: you define the plan as a JSX tree. Each <Task> is a node in a DAG; control flow is a small set of primitives (<Sequence>, <Parallel>, <Branch>, <Ralph>, <Task>).

    After each task completes, Smithers validates the output (Zod) and persists it to SQLite, then re-renders the plan with updated context. If the process crashes, it resumes from the last completed node — no duplicated work, no lost state.

    A quick “hear me out” on React: I tried a bunch of workflow APIs (builder patterns, Python DSLs, Starlark/Bazel-ish rules, even Solid). The thing React gives me that none of those did as cleanly is this: re-rendering is planning. Every step updates durable state, then the “plan function” runs again and produces the next DAG. On top of that you get very readable composition: small reusable workflow components, normal conditionals, and a familiar mental model for evolving systems.

    The part that’s been most useful in practice: I write Smithers scripts with AI, and then have AI monitor runs and iterate on the workflow while it executes (fix prompt/schema/logic issues, adjust steps, improve components). Because state is durable and the plan is declarative, the workflow can evolve without throwing away progress.

    What I’d love feedback on is usability:

    - Would you use this? For what kinds of workflows?

    - Does the API feel natural (Task IDs, context access, retries/loops, composition)?

    - What observability would you expect (why a node ran, plan diffs between renders, traces, run UI/CLI)?

    - What’s missing for real-world runs (cancellation, rate limits, caching, backpressure, concurrency controls)?

    Repo: https://github.com/evmts/smithers

    Article I wrote: https://x.com/FUCORY/status/2021442919299940381