Tide

Workflow API

defineWorkflow, the workflow context, step, hitl, the VFS, and time.

A workflow is a TypeScript module that export defaults { schema, main }. Most of the API is global — no imports — while the typed authoring entry is importable from the virtual tide module. Type definitions live in runtime/src/tide.d.ts.

The workflow shape

const schema = S.object({ name: S.text() });

export default {
  schema,                                   // built with S — validates input
  main: async (ctx: Infer<typeof schema>) => {
    // ctx is the validated, defaulted input
  },
};

defineWorkflow

defineWorkflow is typed sugar over { schema, main }: it gives the body a discoverable ctx and (optionally) a typed Argon client. It returns { schema, main }, so the module still export defaults its result.

import { defineWorkflow, S } from "tide";

export default defineWorkflow({
  argon: sdk,                  // optional: the generated typed Argon SDK
  input: S.object({ ... }),    // optional: defaults to S.object({})
  async run(input, ctx) {      // input typed via Infer<typeof input>
    // ...
  },
});

The workflow context (ctx)

FieldWhat it is
argonThe typed, in-process, journaled Argon client — present and typed only when an argon SDK was passed. See Driving Argon.
stepJournaled, replayable step runner.
hitlHuman-in-the-loop wait (hitl.wait(...)).
llmLarge-language-model calls (ai.llm).
aiThe full ai.* surface (llm, agent, tool, code).
log, sleep, readFile, writeFile, readFileBytes, writeFileBytes, removeFile, listFilesThe sandbox capabilities.

The same capabilities are available as globals in the core { schema, main } form.

step

step<T>(name: string, fn: () => Promise<T>, opts?: { retries?: number }): Promise<T>

Runs fn as an atomic, journaled transaction. On success its return value is recorded; on replay a completed step returns that value without re-running the body. On failure the step's buffered operations and VFS changes are rolled back. With { retries: n } the body is retried up to n times before the error propagates. Nested steps are not supported. See Steps.

const result = await step("charge", async () => {
  await writeFile("receipt.txt", "charged");
  return { ok: true };
}, { retries: 3 });

hitl

hitl.wait(request: HitlWaitRequest): Promise<HumanWaitOutcome>

Suspends the run for a human decision; resumes via tide resume. request requires a title; description, tags, priority, payload, classification, moduleName, and others are optional. The returned outcome carries action, payload, comment, resolvedBy, and resolvedAt. See Human-in-the-loop.

Virtual file system

All file operations run against an in-memory, sandboxed VFS — never the host filesystem. State is derived from journal replay.

FunctionDescription
readFile(path): Promise<string>Read a text file.
writeFile(path, contents): Promise<void>Write a text file.
readFileBytes(path): Promise<Uint8Array>Read a binary file.
writeFileBytes(path, data): Promise<void>Write a Uint8Array.
removeFile(path): Promise<void>Delete a file.
listFiles(path?): Promise<{ name, isFile }[]>List directory entries.

Console and logging

log(...) and console.log(...) write to stdout; console.error(...) to stderr. Output is journaled and replayed deterministically — live logging during replay is suppressed to avoid duplicates. Changing log messages does not break determinism.

Time and sleep

sleep(ms: number): Promise<void>

sleep pauses on first run and is skipped on replay. Date.now() and new Date() return a frozen timestamp captured on first run and replayed thereafter; performance.now() returns 0. See Deterministic time.

AI capabilities

ai.llm.generate(model, prompt, options?) returns text, or a typed object when an outputSchema (built with S) is supplied. ai.agent(...) runs a stateful ReAct tool loop, ai.tool(...) declares a tool, and ai.code.* drives cloud coding agents. These require the host to be configured with the relevant credentials; in the disabled default posture they refuse deterministically. Full signatures are in runtime/src/tide.d.ts.

The tide module exports

Most APIs are global; the importable surface is:

ImportDescription
import { defineWorkflow } from "tide"Typed authoring entry.
import { connectArgon } from "tide"Bind the generated Argon SDK to the journaled client (for tide test files).
import { S, step, log, sleep, hitl, ai, readFile, … } from "tide"The globals, importable when you prefer explicit imports.
import { describe, test, it, assert, expect } from "tide:test"The test harness.

On this page