https://github.com/evmts/smithers
Advanced AI Agents in React
https://github.com/evmts/smithers
Last synced: 4 months ago
JSON representation
Advanced AI Agents in React
- Host: GitHub
- URL: https://github.com/evmts/smithers
- Owner: evmts
- Created: 2026-01-05T21:13:36.000Z (5 months ago)
- Default Branch: main
- Last Pushed: 2026-02-10T12:33:43.000Z (4 months ago)
- Last Synced: 2026-02-10T17:00:10.047Z (4 months ago)
- Language: Swift
- Homepage: https://smithers.sh
- Size: 111 MB
- Stars: 49
- Watchers: 0
- Forks: 4
- Open Issues: 9
-
Metadata Files:
- Readme: README.md
- License: LICENSE
- Agents: AGENTS.md
Awesome Lists containing this project
README
# Smithers
**Deterministic, durable AI workflows defined as React components.**
## What Smithers Does
* Defines workflows as React component trees
* Executes tasks in sequence, parallel, or loops
* Persists every task result to SQLite
* Validates outputs against Zod schemas
* Re-renders the workflow after each step
* Resumes exactly where it left off after crashes
* Supports subscriptions
There is no hidden in-memory state. Every task result is stored as:
```
(runId, nodeId, iteration) → validated output row
```
---
## Example
```tsx
import { createSmithers, Sequence } from "smithers-orchestrator";
import { z } from "zod";
const analyzeSchema = z.object({
summary: z.string(),
severity: z.enum(["low", "medium", "high"]),
});
const fixSchema = z.object({
patch: z.string(),
explanation: z.string(),
});
const { Workflow, Task, smithers, outputs } = createSmithers({
analyze: analyzeSchema,
fix: fixSchema,
});
export default smithers((ctx) => (
{`Analyze the bug: ${ctx.input.description}`}
{`Fix this issue: ${ctx.output("analyze", { nodeId: "analyze" }).summary}`}
));
```
This defines a two-stage DAG:
```
analyze → fix
```
After `analyze` completes:
* Output is validated against `analyzeSchema`
* Written to SQLite
* The tree re-renders
* `fix` becomes runnable
If the process crashes, Smithers resumes from the last completed node.
---
## Install
Requires Bun ≥ 1.3.
```bash
bun add smithers-orchestrator ai @ai-sdk/anthropic zod
```
---
## Mental Model
### 1. React Tree = Execution Plan
Your JSX tree is not UI. It is a declarative execution graph.
* `` is the root.
* `` is a node.
* `` runs children in order.
* `` runs children concurrently.
* `` repeats children until a condition is met.
After each task finishes, Smithers re-renders the tree with updated context.
If new nodes are unblocked, they become runnable.
---
### 2. Zod Schemas = Durable Tables
Each output schema becomes a SQLite table. Pass the schema directly to `` via the `outputs` object returned by `createSmithers`:
```ts
const analyzeSchema = z.object({
summary: z.string(),
severity: z.enum(["low", "medium", "high"]),
});
const { Workflow, Task, smithers, outputs } = createSmithers({
analyze: analyzeSchema,
});
// outputs.analyze === analyzeSchema (the ZodObject, by reference)
```
* Agent output must validate against the schema.
* If validation fails, the task retries (with error feedback).
* Validated output is persisted.
This makes workflows typed, inspectable, and reproducible.
---
### 3. Deterministic Execution
Execution order is:
* Depth-first
* Left-to-right
* Unblocked nodes only
There is no hidden scheduler logic in user code.
---
## Core Components
| Component | Purpose |
| ------------ | ------------------------------ |
| `` | Root container |
| `` | AI or static task node |
| `` | Ordered execution |
| `` | Concurrent execution |
| `` | Conditional execution |
| `` | Loop until condition satisfied |
---
## Validation and Retries
If an agent returns malformed JSON:
1. Smithers appends the validation error to the prompt
2. Retries the task
3. Persists only valid output
```tsx
Analyze the codebase
```
---
## Looping with ``
`` repeats its children until a condition becomes true.
Each iteration is stored separately in the database.
```tsx
Fix based on feedback
Review the implementation
```
---
## Dynamic Branching
Because the workflow re-renders after each task, you can branch with normal JSX:
```tsx
Assess complexity
{ctx.output("assess", { nodeId: "assess" }).complexity === "high" ? (
Plan implementation
) : (
Quick fix
)}
```
---
## CLI
```bash
smithers run workflow.tsx --input '{"description": "Fix bug"}'
smithers resume workflow.tsx --run-id abc123
smithers list workflow.tsx
smithers approve workflow.tsx --run-id abc123 --node-id review
```
---
## Built-in Tools
```tsx
import { read, edit, bash, grep, write } from "smithers-orchestrator";
```
* Sandboxed to workflow root
* `bash` is network-disabled by default
---
## How Execution Works
1. Render React tree
2. Identify runnable tasks
3. Execute task
4. Validate output
5. Persist to SQLite
6. Re-render
7. Repeat
Crash at any point → resume from last persisted step.
---
## When to Use Smithers
* Multi-step AI workflows
* Tool-using agents
* Systems requiring resumability
* Human-in-the-loop review cycles
* Typed, inspectable AI pipelines
Not intended for:
* Single prompt calls
* Stateless toy scripts
---
## License
MIT