Tasks
Reference for the Tasks API, covering endpoints, streaming events, configuration, multi-turn sessions, research tasks, and artifacts.
A task is the simplest way to use Northstar: you describe what you want done, and Northstar operates a computer until the work is done. This page is the reference: endpoints, the event stream, and every configuration option. For a hands-on walkthrough, start with Run a task.
For more control over each step, see the Responses API. For direct computer control without a model, see the Computers API.
Operations
Section titled “Operations”| Operation | SDK call | What it does |
|---|---|---|
| Start (streaming) | client.agent.tasks.start_stream(...) | Starts a task and returns the live SSE event stream |
| Start (async) | client.agent.tasks.start(...) | Returns {task_id, status, idempotency_key, reused} immediately |
| Rejoin a stream | GET /agent/tasks/{id}/stream | Re-subscribe to a running (or just-finished) task’s events |
| Status | client.agent.tasks.retrieve_status(id) | {status, exit_code}: "running" or "completed" |
| Inject a message | client.agent.tasks.inject_message(id, message=...) | Steer, clarify, or ask a follow-up, even mid-execution |
| Pause / resume | client.agent.tasks.pause(id) / .resume(id) | Human take-control between steps |
| Stop | client.agent.tasks.pause(id), or set max_duration_seconds at start | Pause halts between steps; the server also ends a task at its max_duration_seconds deadline. There is no separate cancel call. |
from tzafon import Lightcone
client = Lightcone()
for event in client.agent.tasks.start_stream( instruction="Go to wikipedia.org and summarize today's featured article", kind="browser",): print(event)import Lightcone from "@tzafon/lightcone";
const client = new Lightcone();
const stream = await client.agent.tasks.startStream({ instruction: "Go to wikipedia.org and summarize today's featured article", kind: "browser",});
for await (const event of stream) { console.log(event);}Events
Section titled “Events”When you stream a task, you get a sequence of typed events. Each carries a type and a turn number; the common ones:
| Event | Meaning |
|---|---|
started | Task began, with computer_id, kind, model, and the viewport |
status | Ephemeral progress narration (state + message). Never the final answer; safe to show as a caption and discard |
plan / plan_step_change | The planned checklist, and which item is currently running |
screenshot | A screenshot was captured (image is an HTTPS URL, plus the step) |
executed | A GUI action ran on the computer (action, status) |
answer_delta | A chunk of the assistant’s reply, streamed token-by-token, only when stream_deltas: true |
needs_input | The agent needs a clarification answered in chat: reply with inject_message |
login_required | The agent hit a sign-in wall. A human signs in via the live view, then the task resumes. See Logins and sessions |
message_received / barge_in | Your injected message was accepted (mid-execution injections arrive as barge_in) |
artifact | A file deliverable. See Artifacts |
scratchpad | Live rows accumulating toward a structured deliverable |
suggestions | Suggested follow-up prompts, only when suggestions: true |
computer_parked | An idle multi-turn desktop was snapshotted; it restores automatically (typically under 2s) on your next message |
completed | Task finished successfully: result, model, computer_id, streamed |
failed | Terminal failure: the stream closes; carries status, error_code, retryable |
error | A non-terminal error: the task continues and the stream stays open |
max_steps / max_duration / cancelled | The step limit, wall-clock limit, or a cancellation was reached |
config_error | The request was misconfigured (e.g. an unknown model) |
replay_gap | On reconnect: some buffered events were evicted and couldn’t be replayed |
Research tasks also emit research_swarm_* / research_subtask_* progress events. See Research tasks.
Multi-turn sessions
Section titled “Multi-turn sessions”A task doesn’t have to end at completed. Send a follow-up with inject_message and the agent continues in the same session, with full context and the same computer:
client.agent.tasks.inject_message( task_id, message="Great, now export that table as a CSV",)await client.agent.tasks.injectMessage(taskId, { message: "Great, now export that table as a CSV",});- Mid-execution, your message interrupts the agent (
barge_in). Use it to redirect before it goes further. - Between turns, idle desktops are parked (
computer_parked) to save compute and restored in about a second when your next message arrives. - Sessions stay open for follow-ups for 30 minutes of inactivity.
Resuming a stream
Section titled “Resuming a stream”If your connection drops, re-subscribe without losing events:
curl -N "https://api.tzafon.ai/agent/tasks/{task_id}/stream" \ -H "Authorization: Bearer $TZAFON_API_KEY" \ -H "Last-Event-ID: 42" # or ?from=42Events replay from that sequence number. A replay_gap event means the resume point was evicted from the buffer. Re-check status and continue from live. Streams remain available for about 10 minutes after a task finishes. Pass an idempotency_key when starting tasks so retries of the start call return the same task (reused: true) instead of double-running. See Running in production.
Research tasks
Section titled “Research tasks”For research-shaped instructions, the agent can fan out parallel workers (web search plus isolated browser sessions) and merge the findings. Enable it via allowed_tools:
for event in client.agent.tasks.start_stream( instruction="Compare pricing pages of the top 5 CRM vendors and produce a table", kind="browser", allowed_tools=["desktop_agent", "research_swarm", "artifact_handoff"],): print(event)const stream = await client.agent.tasks.startStream({ instruction: "Compare pricing pages of the top 5 CRM vendors and produce a table", kind: "browser", allowed_tools: ["desktop_agent", "research_swarm", "artifact_handoff"],});Progress arrives as research_swarm_* and research_subtask_* events. allowed_tools also works as a restriction. Pass only ["desktop_agent"] to keep the agent on a single computer.
Artifacts
Section titled “Artifacts”Tasks can deliver files, not just text. When the work produces a deliverable, an artifact event arrives with the file content base64-encoded. Supported kinds include csv, excel, table, html, chart, pdf, docx, and pptx.
import base64
for event in client.agent.tasks.start_stream( instruction="Collect the titles of the top 10 Hacker News stories into a CSV", kind="browser", allowed_tools=["desktop_agent", "artifact_handoff"],): if getattr(event, "type", None) == "artifact": with open(event.filename, "wb") as f: f.write(base64.b64decode(event.data))While the agent gathers rows you’ll see scratchpad events accumulating the data live, which is useful for progress UIs.
Configuration options
Section titled “Configuration options”| Parameter | Default | Description |
|---|---|---|
instruction | : | Plain language description of the work (required) |
kind | : | "desktop" or "browser" (required; start_url implies browser) |
model | latest | Which model to use. Pin a version in production. See Running in production |
system_prompt | : | Extra instructions appended to the agent’s system prompt: persona, domain context, or response style |
context | : | Prior conversation turns ([{role, content}]) to seed the session |
allowed_tools | all | Restrict or enable agent tools: desktop_agent, research_swarm, artifact_handoff |
enable_login_handoff | false | Emit login_required for human sign-in instead of attempting logins. See Logins and sessions |
max_steps | 150 | Maximum number of actions Northstar can take (up to 1000) |
max_duration_seconds | : | Wall-clock limit in seconds; the task is cancelled if it runs longer |
temperature | 0 | Action-model sampling temperature. 0 is deterministic; higher is more exploratory (and less precise at clicking) |
stream_deltas | false | Stream the reply token-by-token as answer_delta events instead of delivering it once at the end |
stream_mode | "verbose" | "concise" trims narration events for lighter streams |
screenshot_mode | "url" | How screenshot events deliver the image: "url" (HTTPS link: smaller events) or "base64" (inline data URL: self-contained, no second fetch) |
suggestions | false | Emit follow-up suggestions events after each turn |
viewport_width / viewport_height | 1280 / 720 | Screen size (320–3840 × 240–2160) |
persistent | false | Save environment state when the computer is terminated (alias: save_session) |
terminate_on_completion | true | Terminate the computer when the task finishes; set false (or keep_alive: true) to keep it running |
computer_id | : | Reuse a live computer, or restore a saved session with that id |
on_missing_computer | "restore" | If computer_id isn’t live: "restore" from its snapshot, "create_new", or "fail" |
environment_id | : | Restore a saved environment snapshot (prefer computer_id) |
start_url | : | Initial URL to open before the agent starts (implies kind: "browser") |
idempotency_key | : | Deduplicate task starts across retries |
thread_id | : | Group multiple tasks belonging to the same conversation |
metadata | : | Arbitrary key/values echoed back in the started event |
See also
Section titled “See also”- Run a task: hands-on walkthrough: streaming, polling, steering, and writing good instructions
- Logins and sessions: persistent sessions and the login handoff
- Observability: live view, screencast, and traces
- Running in production: idempotency, retries, and stream resumption
- Responses API: build your own loop for full control over every step