Skip to main content
A task represents a single conversation thread between your application and an agent or workforce. When you send a message, the SDK returns a Task — everything that happens next flows through it.

The shape of a task

const task = await agent.sendMessage("Hello");

console.log(task.id);     // unique task identifier
console.log(task.name);   // display title
console.log(task.status); // current status

Task status

Every task has a status field. The SDK simplifies the platform’s internal states into a concise set:
StatusMeaning
not-startedCreated locally, not yet sent
idleAgent is idle, awaiting input
pausedExecution has been paused
queuedWaiting to start (capacity, queue)
runningAgent is actively processing
actionRequires approval or has escalated
completedFinished successfully
cancelledCancelled before completion
errorEncountered a failure
The platform uses more granular internal states. The SDK maps them to the statuses above so application code doesn’t need to handle every variation.
Platform stateSDK status
idleidle
starting-upqueued
waiting-for-capacityqueued
queued-for-approvalqueued
queued-for-rerunqueued
runningrunning
pending-approvalaction
escalatedaction
pausedpaused
completedcompleted
cancelledcancelled
timed-outerror
unrecoverableerror
errored-pending-approvalerror
For workforce state mappings, see Workforces.

Is the task still active?

isRunning returns true when the status is queued or running:
if (task.isRunning()) {
  console.log("Agent is working...");
}

Fetch message history

Retrieve every message on a task with getMessages:
const messages = await task.getMessages();
To fetch only messages after a specific point, pass an after date:
const recent = await task.getMessages({
  after: new Date("2025-06-01T00:00:00Z"),
});
Each message is one of the types described in Messaging. The same type guard methods (isAgent, isTool, and so on) work here.

Listen for events

Tasks emit events in real time as the conversation progresses. There are three event types:
EventWhen it fires
"message"A new message is received
"error"An agent error occurs
"update"Task metadata changes (e.g., status)

The “message” event

The primary event for agent responses, tool executions, and streaming content:
task.addEventListener("message", ({ detail }) => {
  const { message } = detail;

  if (message.isAgent()) {
    console.log("Agent:", message.text);
  }
});
For the full set of message types and their fields, see Messaging.

The “error” event

Fires when the agent runs into a failure:
task.addEventListener("error", ({ detail }) => {
  console.error(detail.message.lastError);
});

The “update” event

Fires when the task’s metadata changes, such as a status transition:
task.addEventListener("update", () => {
  console.log("New status:", task.status);
});
The current SDK has a TypeScript type mismatch on this event — the declared event map key differs from the string dispatched at runtime. The "update" string shown above is correct and events fire as expected. If the type checker complains, add // @ts-expect-error above the line until the upstream fix lands.

Subscriptions are automatic

The first call to addEventListener on a task activates its subscription. There’s no need to call subscribe manually. Once subscribed, the SDK keeps the task up to date by polling for new messages and metadata changes, and opens a streaming connection when available to deliver real-time thinking and typing events. See Streaming for details. The SDK manages the polling frequency internally — faster when the task is active, slower when idle. This is transparent to the application.

Clean up

Always call unsubscribe when a task is no longer needed. This stops the polling loop and closes any active connections, freeing network and memory resources.
task.unsubscribe();
Failing to unsubscribe from tasks that have left scope is a common source of resource leaks. In component-based UI frameworks, call unsubscribe from the cleanup or teardown handler.
useEffect(() => {
  const handler = ({ detail }) => {
    setMessages((prev) => [...prev, detail.message]);
  };

  task.addEventListener("message", handler);

  return () => {
    task.unsubscribe();
  };
}, [task]);