Docs/Actor starts

Actor starts

Use an Actor for one stable identity with many managed Runs over time. The Actor declaration binds its implementation; callers supply a key or use the returned Actor ID, one explicit Workspace, and optional initial input.

const started = await reviewer.start({
  key: "github:OWNER/REPO#42",
  workspace: { key: "github:OWNER/REPO#42" },
  input: { type: "review", owner: "OWNER", repo: "REPO", prNumber: 42 },
  idempotencyKey: "github:OWNER/REPO#42:start",
})

The optional initial value is sequence 1 of the ordinary Actor input log. It is not a separate handler payload. A matching live start claim replays the same Actor and boot Run; an occupied key from a different request conflicts.

Actor code consumes input and publishes progressive durable output:

export const reviewer = actor({
  id: "reviewer",
  async run(self) {
    const input = await self.input.receive({ idleTimeout: "30m" }).unwrap()
    await self.output.append({ type: "progress", message: "Reviewing", input })
  },
})

Later messages use the same fixed input channel:

const ref = reviewer.ref({ key: "github:OWNER/REPO#42" })
await ref.input.send(
  { type: "steer", instruction: "Please also update the tests." },
  { idempotencyKey: "slack:T123:C456:1712345678.000100" },
)

for (const record of await ref.output.list()) {
  console.log(record.sequence, record.data)
}

Use a direct Task Run for bounded one-shot work. Its durable application output is the terminal result; it has logs and events but no named input/output streams.

For an email link or one browser approval button, use a Token instead of granting channel access. Actor-channel public browser grants are deferred in v0; token.complete is the retained narrow public capability.