Typed State
You want a typed state shape for a route, including the values needed to run it. Here's how.
The code
import { z } from "zod"
export default z.object({
/** Tenant supplied in the run input */
tenant: z.string(),
/** Accumulated tool-call results */
context: z.string().default(""),
/** Number of records returned by the lookup tool */
count: z.number().default(0),
})Notes
-
Include route values in the schema.
[tenant]is part of the route id; the workflow validatestenantfrom the input by callingstate.parse(input). -
Route ids stay parameterized. Run this route as
/hello/[tenant]with input fortenant:bashecho '{"tenant":"acme"}' | dawn run '/hello/[tenant]'For an Agent Protocol run, send the same input in the body:
json{ "route": "/hello/[tenant]#workflow", "input": { "tenant": "acme" } }A concrete
/hello/acmepath is not how Dawn populates route state. -
Parse workflow input explicitly. Workflow routes do not automatically parse
state.ts. Callingstate.parse(input)validates the input and applies fields declared with.default(...)when the caller omits them. -
This workflow imports and parses the schema directly. It can keep
tenantrequired. For agent-state discovery, Dawn instead validates{}to extract defaults; if you reuse this schema for an agent route, make every top-level field accept missing input so discovery does not skip it. -
State is JSON-serializable. It crosses the runtime boundary on every
runs/waitandruns/streamcall. Use primitives, plain objects, arrays.