{"id":50667685,"url":"https://github.com/b4fun/smol-workflows","last_synced_at":"2026-06-08T08:00:57.281Z","repository":{"id":362225031,"uuid":"1254911270","full_name":"b4fun/smol-workflows","owner":"b4fun","description":null,"archived":false,"fork":false,"pushed_at":"2026-06-03T06:44:47.000Z","size":330,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-03T08:27:05.236Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/b4fun.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-31T06:40:57.000Z","updated_at":"2026-06-03T06:43:31.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/b4fun/smol-workflows","commit_stats":null,"previous_names":["b4fun/smol-workflows"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/b4fun/smol-workflows","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/b4fun%2Fsmol-workflows","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/b4fun%2Fsmol-workflows/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/b4fun%2Fsmol-workflows/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/b4fun%2Fsmol-workflows/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/b4fun","download_url":"https://codeload.github.com/b4fun/smol-workflows/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/b4fun%2Fsmol-workflows/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34053435,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-08T02:00:07.615Z","response_time":111,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-08T08:00:29.063Z","updated_at":"2026-06-08T08:00:57.267Z","avatar_url":"https://github.com/b4fun.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# smol-workflows\n\nMinimal agentic workflow runtime for orchestrating your agents at scale.\n\n`smol-workflows` runs ES-module workflow scripts inside a self-contained Rust/QuickJS engine. Workflows use injected workflow primitives such as `agent`, `parallel`, `pipeline`, `workflow`, `budget`, `phase`, and `log`; agent calls are checkpointed in SQLite so interrupted runs can be resumed without re-running completed provider steps.\n\n## Getting Started\n\n### Installing\n\nDownload the latest release into the current directory:\n\n```sh\n# Linux x86_64\ncurl -fsSL https://github.com/b4fun/smol-workflows/releases/latest/download/smol-wf-linux-x86_64.tar.gz | tar -xz\n\n# macOS Apple Silicon\ncurl -fsSL https://github.com/b4fun/smol-workflows/releases/latest/download/smol-wf-macos-aarch64.tar.gz | tar -xz\n```\n\n### Running your first workflow\n\nHere is a workflow that uses `agent`, `parallel`, and `pipeline` to diagnose Kubernetes pod status. This example is also available at [`examples/pod-diagnostics.mjs`](examples/pod-diagnostics.mjs):\n\n```js\nexport const meta = {\n  name: 'pod-diagnostics',\n  description: 'Diagnose Kubernetes pod status with agent, parallel, and pipeline primitives',\n  phases: [\n    { title: 'Discover', detail: 'Find the target pods', model: 'github-copilot/gpt-5.4-mini' },\n    { title: 'Inspect', detail: 'Gather metrics and logs for each pod', model: 'github-copilot/gpt-5.4-mini' },\n    { title: 'Summarize', detail: 'Generate diagnostic guidance', model: 'github-copilot/gpt-5.5' },\n  ],\n}\n\nconst target = typeof args.target === 'string'\n  ? args.target\n  : 'pods that look unhealthy in the current Kubernetes context'\n\nconst POD_LIST_SCHEMA = {\n  type: 'object',\n  properties: {\n    pods: {\n      type: 'array',\n      items: {\n        type: 'object',\n        properties: {\n          namespace: { type: 'string' },\n          name: { type: 'string' },\n          reason: { type: 'string' },\n        },\n        required: ['namespace', 'name', 'reason'],\n        additionalProperties: false,\n      },\n    },\n  },\n  required: ['pods'],\n  additionalProperties: false,\n}\n\nphase('Discover')\nconst { pods } = await agent(\n  `List Kubernetes pods to inspect for this request: ${target}. Use kubectl if needed.`,\n  { schema: POD_LIST_SCHEMA },\n)\n\nphase('Inspect')\nconst inspections = await parallel(pods.map((pod) =\u003e async () =\u003e {\n  const [inspection] = await pipeline(\n    [pod],\n    (currentPod) =\u003e agent(\n      `Get recent metrics and status for pod ${currentPod.namespace}/${currentPod.name}.\nInclude restarts, readiness, CPU/memory, events, and current phase.`,\n      { phase: 'Inspect' },\n    ),\n    (metrics, currentPod) =\u003e agent(\n      `Get relevant recent logs for pod ${currentPod.namespace}/${currentPod.name}.\nFocus on errors, crashes, probes, and startup failures.\nMetrics/status context:\n${metrics}`,\n      { phase: 'Inspect' },\n    ),\n  )\n\n  return { pod, inspection }\n}))\n\nphase('Summarize')\nconst diagnostics = await agent(\n  `Summarize Kubernetes pod diagnostics for: ${target}\nFor each pod, identify likely status, evidence, severity, and next actions.\n${JSON.stringify(inspections, null, 2)}`,\n)\n\nexport default { target, pods, inspections, diagnostics }\n```\n\nSave the code above to `pod-diagnostics.mjs`, then run it with your preferred provider and a natural-language target:\n\n```sh\nsmol-wf run ./pod-diagnostics.mjs \\\n  --agent-provider pi \\\n  --args-target \"coredns pods under kube-system\" \\\n  | tee pod-diagnostics.json \\\n  | jq -r '.results.diagnostics'\n```\n\nExample diagnostic output:\n\n```md\n[phase] Discover\n[phase] Inspect\n[phase] Summarize\n## Kubernetes Pod Diagnostics Summary: CoreDNS pods in `kube-system`\n\n### Overall assessment\n\nBoth CoreDNS pods appear healthy and operational.\n\nThe only recurring log messages are warnings about missing optional CoreDNS customization files:\n\n- `No files matching import glob pattern: custom/*.override`\n- `No files matching import glob pattern: custom/*.server`\n\nThese are typically benign when no custom CoreDNS override/server files are configured.\n\n### Pod: `kube-system/coredns-...-2ngp4`\n\n- Status: Running\n- Readiness: 1/1 Ready\n- Restarts: 0\n- Events: none\n- Severity: Low / Informational\n\n### Pod: `kube-system/coredns-...-vck6j`\n\n- Status: Running\n- Readiness: 1/1 Ready\n- Restarts: 0\n- Events: none\n- Severity: Low / Informational\n\n### Final conclusion\n\nBoth requested CoreDNS pods are Running, Ready, and not restarting. There is no evidence of operational failure from the provided diagnostics.\n```\n\n`smol-wf run` writes progress such as `[phase] ...` and `[log] ...` to stderr, and writes the final JSON report to stdout. The JSON report includes:\n\n- `runID` — workflow run identifier;\n- `tokenUsage` — aggregate `inputTokens`, `outputTokens`, and `totalTokens`;\n- `results` — the workflow's returned data.\n\nExplore more workflows under the [`examples`](examples) folder.\n\nYou can inspect persisted run records later with `smol-wf history`:\n\n```sh\n# List recent workflow runs from the default platform app-state workflows.db\nsmol-wf history\n\n# Show details for a specific run, including attempts, steps, usage, sessions,\n# model metadata, and isolation metadata when present\nsmol-wf history run_01kt...\n\n# Machine-readable detail output\nsmol-wf history run_01kt... --output json | jq '.steps'\n```\n\n### Installing in Code Agents\n\nAsk your code agent to read the [harness installation instructions](https://github.com/b4fun/smol-workflows/blob/main/harness/README.md) and install the smol-workflows harness integration for itself.\n\nThese integrations add smol-workflows skills/tools to the host agent. They do not install the `smol-wf` binary itself; the bundled helper resolves an existing binary, builds from a nearby checkout when possible, or downloads a release archive.\n\n## Workflow shape and primitives\n\nWorkflows are ES modules. The Rust runner injects workflow primitives before evaluating the script. A primitive is a small built-in capability the workflow can call directly, such as running an agent, fanning work out in parallel, or marking progress. The TypeScript definitions for these globals live in [`ts/sdk/src/index.ts`](ts/sdk/src/index.ts) and [`ts/sdk/src/pipeline.ts`](ts/sdk/src/pipeline.ts).\n\nA workflow script should export:\n\n```ts\nexport const meta: WorkflowMetadata\nexport default resultOrWorkflowFunction\n```\n\n### `args` -- Workflow input values supplied by the CLI or parent workflow\n\n```ts\nargs: Record\u003cstring, unknown\u003e\n```\n\n\u003cdetails\u003e\n\u003csummary\u003eDetails\u003c/summary\u003e\n\nInput arguments passed by `smol-wf run --args-*` or `--args-from-file`. Treat values as untrusted JSON and narrow them before use.\n\n\u003c/details\u003e\n\n### `agent(prompt, options?)` -- Send a prompt to a provider and get text or structured JSON back\n\n```ts\nagent(prompt: string, options?: AgentRunOptions): Promise\u003cstring | null\u003e\nagent(prompt: string, { schema, ...options }): Promise\u003cFromSchema\u003ctypeof schema\u003e | null\u003e\n```\n\n\u003cdetails\u003e\n\u003csummary\u003eDetails\u003c/summary\u003e\n\nRuns one agent/provider call. By default it returns text. With `schema`, it requests structured JSON and the engine validates the result against that JSON Schema. Useful options include:\n\n- `phase` — associate the call with a phase for tracing and token usage grouping;\n- `schema` — JSON Schema for structured output;\n- `model` — provider-specific model override;\n- `provider` — provider override such as `pi`, `opencode`, `codex`, or `claude-code`;\n- `isolation: \"worktree\"` — run the agent in an engine-managed temporary git worktree;\n- `agentType` — provider-specific subagent/agent selection.\n\nIf an agent call fails inside `parallel` or `pipeline`, that item/task resolves to `null`; otherwise errors reject the workflow.\n\n\u003c/details\u003e\n\n### `parallel(tasks)` -- Run independent async tasks concurrently and collect their results\n\n```ts\nparallel(tasks: Array\u003c() =\u003e Awaitable\u003cT\u003e\u003e): Promise\u003cArray\u003cT | null\u003e\u003e\n```\n\n\u003cdetails\u003e\n\u003csummary\u003eDetails\u003c/summary\u003e\n\nRuns independent tasks concurrently and returns results in input order. If one task throws, only that task becomes `null`; sibling tasks can still complete. Use this when there is a real barrier before the next workflow step.\n\n\u003c/details\u003e\n\n### `pipeline(items, ...stages)` -- Move each item through ordered stages as soon as it is ready\n\n```ts\npipeline(\n  items: readonly Item[],\n  ...stages: Array\u003c(previous, item, index) =\u003e Awaitable\u003cNext\u003e\u003e\n): Promise\u003cArray\u003cFinal | null\u003e\u003e\n```\n\n\u003cdetails\u003e\n\u003csummary\u003eDetails\u003c/summary\u003e\n\nRuns each item through sequential stages without a global barrier between stages. Each stage receives:\n\n- `previous` — the previous stage result, or the original item for the first stage;\n- `item` — the original input item;\n- `index` — the item index.\n\nIf a stage throws for one item, that item becomes `null` and later stages for that item are skipped.\n\n\u003c/details\u003e\n\n### `workflow(nameOrRef, args?)` -- Invoke another workflow as a child step\n\n```ts\nworkflow(nameOrRef: string | { scriptPath: string }, args?: unknown): Promise\u003cunknown\u003e\n```\n\n\u003cdetails\u003e\n\u003csummary\u003eDetails\u003c/summary\u003e\n\nRuns another workflow as a child workflow. Relative `scriptPath` values resolve from the current workflow file. The current engine supports one level of child workflow nesting.\n\n\u003c/details\u003e\n\n### `budget` -- Inspect the shared token-budget view for budget-aware prompts and decisions\n\n```ts\nbudget: {\n  total: number | null\n  spent(): number\n  remaining(): number\n}\n```\n\n\u003cdetails\u003e\n\u003csummary\u003eDetails\u003c/summary\u003e\n\nExposes the soft output-token budget. `total` is set by `--budget-allowance`; `spent()` is accumulated from provider-reported output tokens; `remaining()` is `Infinity` when no allowance is configured.\n\n\u003c/details\u003e\n\n### `phase(name, options?)` -- Mark the current workflow phase for logs, tracing, and phase defaults\n\n```ts\nphase(name: string, options?: unknown): void\n```\n\n\u003cdetails\u003e\n\u003csummary\u003eDetails\u003c/summary\u003e\n\nMarks workflow progress. Phases are printed to stderr, included in run history, and used to apply phase-level metadata defaults such as `model` and `provider`.\n\n\u003c/details\u003e\n\n### `log(...values)` -- Write progress/debug messages without changing workflow results\n\n```ts\nlog(...values: unknown[]): void\n```\n\n\u003cdetails\u003e\n\u003csummary\u003eDetails\u003c/summary\u003e\n\nWrites workflow progress/debug information to stderr without changing the workflow result.\n\n\u003c/details\u003e\n\n## Usage\n\n### CLI\n\n| Command group | Purpose | Reference |\n| --- | --- | --- |\n| `smol-wf run` | Run a workflow script. | [`docs/usages/run.md`](docs/usages/run.md) |\n| `smol-wf tui` | Interactively stream or replay workflow events in a terminal UI. | [`docs/usages/tui.md`](docs/usages/tui.md) |\n| `smol-wf history` | Get workflow runs history. | [`docs/usages/history.md`](docs/usages/history.md) |\n| `smol-wf llm` | LLM-facing helper commands, such as workflow discovery. | [`docs/usages/llm.md`](docs/usages/llm.md) |\n\n### Terminal UI\n\nUse the TUI to observe workflows live or replay a saved event stream.\n\n![smol-wf TUI live workflow demo](docs/assets/smol-wf-tui-stock-demo-30s.gif)\n\n```sh\n# Run a workflow with live event visibility.\nsmol-wf tui run ./workflow.mjs --agent-provider pi --args-target \"coredns pods under kube-system\"\n\n# Save an event stream from a normal run, then replay it.\nsmol-wf run ./workflow.mjs --events \u003e events.jsonl\nsmol-wf tui replay events.jsonl\n\n# Validate/summarize an event stream without opening the interactive UI.\nsmol-wf tui replay events.jsonl --check\n```\n\nThe live TUI shows workflow scopes, provider events, token usage, an event-rate graph, selected-event details, and raw/pretty views. Live event logs start unsaved; after the workflow stops, press `s` or choose `save \u0026 quit` to write `$PWD/\u003crun-id\u003e.jsonl`. Replay starts paused with zero revealed events and advances according to `elapsedNanos`, with long gaps capped by `--max-delay` (`50ms` by default).\n\nSee [`docs/usages/tui.md`](docs/usages/tui.md) for keybindings and replay options.\n\n## Agent providers\n\nThe engine includes built-in agent providers for `debug`, `codex`, `claude-code`, `pi`, and `opencode`. Providers can be selected globally with `--agent-provider` or per call with `agent(prompt, { provider })`.\n\nStructured output schemas are validated by the Rust engine, with one retry using a schema-validation prompt when a provider result does not match. Agent calls can also opt into per-call provider retries with `agent(prompt, { retry: { maxAttempts, backoffMs } })`. See [`docs/workflow/retry.md`](docs/workflow/retry.md) and [`docs/harness-capabilities`](docs/harness-capabilities) for provider capability notes, including provider-specific structured-output behavior, input/environment capability expectations, and budget/usage tracking behavior.\n\n## Durable backends\n\nDurable workflow runs use the Rust SQLite backend. The CLI uses this backend by default and stores run/task/step state, completed agent checkpoints, provider results, and budget ledger entries in the platform app-state `workflows.db` unless `--db` is provided. Runs are not retried globally; use per-agent retry settings for transient provider failures and `--resume-run \u003crun-id\u003e` to explicitly continue an existing run. See [`docs/usages/config.md`](docs/usages/config.md) for default database locations.\n\n## What is in this repo\n\n- `rust/engine` — Rust workflow engine with a sandboxed QuickJS runtime, metadata extraction, schema validation, budget accounting, built-in agent providers, and a SQLite durable backend.\n- `rust/cli` — `smol-wf` command-line interface for running and discovering workflows.\n- `ts/sdk` — TypeScript types for workflow authors (`@smol-workflows/sdk`).\n- `harness` — integrations and skills for code-agent hosts.\n- `examples` — runnable workflow scripts.\n- `docs` — design notes, workflow API reference, and harness capability notes.\n\n## TODOs\n\n- [ ] improve context passing between agents; provide primitives for propagated context and workflow/pre-defined memory data\n- [ ] environment abstraction\n- [ ] environment sandbox / isolation\n- [ ] remote environment support\n- [ ] human in the loop / steering support\n- [ ] cross-run aggregate budget reporting\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fb4fun%2Fsmol-workflows","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fb4fun%2Fsmol-workflows","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fb4fun%2Fsmol-workflows/lists"}