Docs / Human input

Human input

Use tokens before side effects such as posting to GitHub, deploying, or changing infrastructure. Helmr parks the run durably; your Slack, email, Linear, or app-server bridge delivers the token and completes it.

import { task, tokens } from "@helmr/sdk"

export const publishReview = task({
  id: "publish-review",
  run: async () => {
    const token = await tokens.create({
      timeout: "30m",
      tags: ["approval", "github"],
      metadata: { action: "publish-review" },
    })

    await sendSlackApproval({
      tokenId: token.id,
    })

    const decision = await token.wait({
      schema: approvalDecisionSchema,
    }).unwrap()

    if (!decision.approved) return { status: "skipped" }
    await postReview()
    return { status: "posted" }
  },
})

Complete the token from a userland bridge:

await client.tokens.complete(token.id, {
  approved: true,
  actor: "slack:U123",
})

Browser or raw HTTP action handlers can complete the same token with Authorization: Bearer ${token.publicAccessToken} on /api/v1/tokens/{tokenId}/complete. Server-to-server webhook handlers can use token.callbackUrl when a pre-signed completion URL is a better fit.

Operators can inspect the relevant session and run attempts from the CLI:

helmr session get SESSION_ID
helmr run list --session SESSION_ID

Only one blocking token, stream, or timer wait can be active at a time in a task. Await each wait before starting the next one.