Build a durable agent
Tasks are a good fit for bounded one-shot work. An Actor adds a stable Session with ordered input and output, while each period of execution is still a Run.
Define the Actor
Add a declaration beside your existing Sandbox:
import { actor } from "@helmr/sdk"
export const assistant = actor({
id: "assistant",
idleTimeout: "30m",
async run(session, ctx) {
await session.output.append({
type: "ready",
runId: ctx.run.id,
workspaceId: ctx.workspace.id,
})
while (!ctx.signal.aborted) {
const message = await session.input.receive({
idleTimeout: "30m",
})
if (!message.ok) return
await session.output.append({
type: "reply",
inputSequence: message.record.sequence,
text: `received: ${JSON.stringify(message.value)}`,
})
}
},
})
receive() can durably park the managed Run. New input resumes work without
discarding the Session’s identity or ordered history. A later continuation may
use a different Run ID.
Deploy and start
helmr deploy . --project demo --env development
WORKSPACE_ID="$(helmr workspace create hello \
--project demo --env development \
--key tutorial:assistant \
--idempotency-key tutorial:assistant:workspace)"
helmr actor start assistant \
--project demo --env development \
--workspace "$WORKSPACE_ID" \
--key user:ada \
--input-json '{"type":"message","text":"hello"}' \
--idempotency-key tutorial:assistant:start \
--json
The response contains both session_id and the boot run_id. Save the Session
ID for all later interaction.
Continue the Session
helmr actor input send SESSION_ID \
--project demo --env development \
--input-json '{"type":"message","text":"summarize our work"}' \
--idempotency-key tutorial:assistant:message:2
helmr actor output read SESSION_ID \
--project demo --env development \
--after 0 --jsonl
Output reads are finite pages. Pass the last durable sequence back through
--after to read only newer records. Input idempotency keys should come from a
stable upstream event ID so delivery retries do not duplicate application
commands.
Inspect the current managed Run with helmr actor get SESSION_ID. When the
conversation is finished, close the Session explicitly:
helmr actor close SESSION_ID \
--project demo --env development \
--idempotency-key tutorial:assistant:close
Closing stops future input admission; it does not turn Actor output into Run logs. Use the Session output channel for application messages and Run logs and events for execution diagnostics.