Start and observe a Session
This guide starts a deployed Agent, follows its progress and continues the
conversation, first with the CLI and then with the TypeScript SDK. The examples
use an Agent with the definition ID reviewer in the demo Project’s staging
Environment, with the CLI configured (see Quickstart). With
an Environment API key, omit --project and --env.
For what Sessions and Turns are, see Sessions and Turns.
Start the Agent
helmr session create reviewer --project demo --env staging \
--text "Review issue 42" \
--key issue-42 \
--idempotency-key issue-42:start
The command prints the new session_id and turn_id; add --json for the full
receipt. Input can be given in one of three ways:
| Flag | Input |
|---|---|
--text TEXT |
One text part, whitespace preserved. |
--input-json JSON |
A JSON array of text parts, such as [{"type":"text","text":"Review issue 42"}]. Omit input flags for zero Turns; [] is rejected. |
--input-file PATH |
The same JSON array, read from a file. |
--key uniquely names the Session within its Agent; another creation with that
key conflicts. Use session list --agent AGENT --key issue-42 to find it, using the Agent identifier declared in code.
--idempotency-key identifies this creation request: repeat the same request
with that key after an uncertain failure to recover its receipt.
Without --computer, Helmr creates a new Computer from the Agent’s definition.
Pass --computer COMPUTER_ID to run the Session on an existing Computer. To post
the Session in a Slack channel, see Connect an Agent to Slack.
Read events
helmr session events SESSION_ID --project demo --env staging
Each line is one record: its sequence number, kind and data. Records include the
Turn’s progress output (turn.output), status changes, questions and Session
controls; see Session events. One call returns one
page of up to 100 records (--limit up to 1000). When more records exist, the
output ends with next_after: N; pass that value as --after to read the next
page:
helmr session events SESSION_ID --project demo --env staging --after 57
Use --json for one JSON page or --jsonl for one record per line. Events can be
read while the Turn runs and after it finishes. The end of the event list does not
mean the Turn has finished; read the Turn’s status for that.
Wait for the Turn
helmr session turn wait TURN_ID --session SESSION_ID --timeout 10m \
--project demo --env staging --json
The command polls until the Turn settles or the timeout passes. It prints
{"status":"settled","outcome":{...}} with the Turn’s final status, result,
response and error, or {"status":"timeout"}. A timeout stops only the wait; the
Turn keeps running and you can wait again with the same IDs.
Send follow-ups
Add a new Turn to the Session:
helmr session enqueue SESSION_ID --project demo --env staging \
--text "Also check the tests" --idempotency-key issue-42:tests
Enqueue always creates a new Turn, even while another Turn is running; Turns run
one at a time in order. The receipt includes the new turn_id.
To steer the work that is running now, send a message instead:
helmr session turn send TURN_ID --session SESSION_ID --project demo --env staging \
--text "Skip the generated files" --idempotency-key issue-42:steer
session turn send targets the given running Turn. If it cannot accept messages,
the request is rejected. The Agent receives messages through turn.onMessage.
Use enqueue explicitly when you want new work.
Inspect the outcome
helmr session get SESSION_ID --project demo --env staging
helmr session turn list --session SESSION_ID --project demo --env staging
helmr session turn get TURN_ID --session SESSION_ID --project demo --env staging --json
session get shows the Session’s status, Agent, Computer and any holds.
session turn list lists its Turns in order with their status. session turn get
shows one Turn’s status and, once it has settled, its result, response or error.
| Turn status | Meaning |
|---|---|
queued, running |
Not settled yet. |
completed |
Finished; the result and response are available. |
failed, interrupted, cancelled |
Settled without completing; read error. |
A Turn waiting for a person to answer a question stays running. See
Answer questions.
When you are done with the conversation, close the Session:
helmr session close SESSION_ID --project demo --env staging
Do the same with the SDK
Construct a HelmrClient with your control plane’s origin and an
Environment API key:
import { HelmrClient } from "@helmr/sdk"
const client = new HelmrClient({
url: process.env.HELMR_API_URL!,
apiKey: process.env.HELMR_API_KEY!,
})
const { session, turn } = await client.sessions.create({ agent: "reviewer", input: [{ type: "text", text: "Review issue 42" }],
key: "issue-42",
idempotencyKey: "issue-42:start", })
// Print progress while waiting for the first Turn.
const watcher = new AbortController()
const progress = (async () => {
try {
for await (const event of session.events.stream({ after: 0 }, { signal: watcher.signal })) {
if (event.kind === "turn.output") console.log(event.data)
}
} catch (error) {
if (!watcher.signal.aborted) throw error
}
})()
const first = await turn.wait({ timeout: "10m" })
if (first.status === "settled") {
console.log(first.outcome.status, first.outcome.result, first.outcome.response)
}
// Add a follow-up Turn and wait for it.
const next = await session.enqueue(
[{ type: "text", text: "Also check the tests" }],
{ idempotencyKey: "issue-42:tests" },
)
const second = await next.wait({ timeout: "10m" })
watcher.abort()
await progress
await session.close()
| Call | Result |
|---|---|
client.sessions.create({ agent: name, ...request }) |
{ session, turn }. Pass computer: { id } to use an existing Computer. |
session.events.list({ after?, limit? }) |
One page: records, nextAfter, hasMore. |
session.events.stream({ after? }) |
An async iterator that keeps polling for new records until aborted. |
turn.wait({ timeout }) |
{ status: "settled", outcome } or { status: "timeout" }. Without timeout, waits for the outcome. |
turn.get() |
The Turn’s current state. |
session.enqueue(input, { idempotencyKey }) |
A reference to the new Turn. |
session.turns.ref(id).send(message) |
A message to exactly that Turn. |
To reconnect later, keep the IDs and rebuild the references with
client.sessions.ref(sessionId) and session.turns.ref(turnId). See the
client reference for every method.