novo agents

Changelog

Customer-facing release notes for the novoagents SDK and hosted API contract. Internal engine, routing, and infrastructure changes are intentionally omitted.

Unreleased

  • Thinking and activity progress. Set streamProgress: true on runs.start or threads.stream to receive one provider-neutral, replace-in-place data-novo-progress line across thinking, public tool activity, and delegated waits. kind distinguishes a short, reasoning-derived summary from deterministic runtime activity; this surface never exposes raw reasoning. summaryAvailable is explicitly false when safe readable reasoning is unavailable. Browser and React state expose the latest snapshot as progress and clear it at answer, restart, pause, and terminal boundaries. Enabling progress does not change reasoning effort. The public stream schema is now 2.

  • Idempotency keys remain reserved for 24 hours. A matching create, message, or run-start retry whose first result is still pending now returns 503 service_unavailable for the full retention window instead of risking a duplicate. Retry the same request and key later; after 24 hours, the key may be reused for a new operation.

  • Credits are prepaid through explicit purchases. The console keeps its hosted Stripe Checkout flow, while the prelaunch auto-recharge and saved-card settings have been removed. novo.credits.retrieve() now returns current balance and account-limit usage without auto-reload state.

  • Word and PowerPoint common styles are format-aware. font objects, dotted font properties, and horizontal alignment objects now normalize to the target format's native operation fields. Conflicting or unsupported structured styles return an indexed document_operation_invalid error; verified rawPropEntries remain exact.

  • Completed run replays wait for durable history. If a completed workflow becomes visible just before its durable stream is readable, the run stream reopens from the same cursor through its bounded reconnect window before it reports history: 'incomplete'. Failed and cancelled Workflow executions retain their immediate terminal fallback.

  • SDK final results honor durable model-attempt recovery. finalResult and streamToCompletion() now derive assistant text through the canonical Novo reducer. Targeted model-step retractions, terminal tail repair, and reconnect replay de-duplication therefore produce the same authoritative text as the browser run engine.

  • Model-step reexecutions retract only abandoned content. A durable model-producer reexecution emits data-novo-model-step-restart before successor content with the exact text/reasoning, tool-call, and source ids to remove. Model chunks without a stable target id remain server-side until the step commits. The Novo browser reducer applies targeted removals automatically; the existing data-novo-step-restart remains completion-step diagnostics and never authorizes content removal. A public projection repair is also identified by data-novo-step-terminal.data.perf.streamIntegrity; its repair kind is now model_step_reexecution, not workflow_step_retry, because another execution does not prove why Workflow scheduled it.

  • First-response stage timing. data-novo-step-terminal.data.perf adds replay-safe turnStartedAt, contextReadyAt, modelRequestAt, and firstTokenAt instants plus TTFT-excluded realStreamMs / decodeTps. Combine the step-0 terminal with run-meta createdAt / startedAt; derive prompt-cache use from the existing cumulative usage.cacheReadTokens.

  • Thread creation reports fresh versus replayed. threads.create() now returns ThreadCreateResponse, adding created: true for a fresh thread and created: false for a successful idempotency replay. Both remain HTTP 201.

  • Browser tasks can choose saved-login or isolated identity. browser_navigate accepts sessionMode: 'authenticated' | 'isolated'; authenticated mode requires a configured profile. A busy profile returns a non-retryable error with isolatedAvailable: true; Novo never silently downgrades an authenticated task, and isolated sessions never touch profile cookies or storage.

  • Workspace export has one strict file contract. workspace_export_artifact({ path, filename?, mimeType? }) accepts a file path only. To deliver a directory, create an archive file in the workspace first and export that file, or export the required files individually when shell is unavailable. Usage docs also clarify that run input totals accumulate across model calls and include cache-read tokens as a subset.

  • Tool approval delivery has an explicit ceiling. A review hook remains one delivery with no automatic retry. requestTimeoutMs now has a documented hard ceiling of 790 seconds; return pause and resolve later when the decision cannot complete synchronously.

  • Sharper framing on the landing page. The hero now states the deal directly (the most capable agents in your stack, none of the complexity), and the copy makes explicit that runs are never a black box: every step an agent takes streams into your UI as it happens.

  • The docs are now fully agent-readable. New stable URLs: /setup.md, a setup skill your coding agent follows to wire Novo into a project end to end (also embedded with one-click copy at /docs/setup and in the console); /llms.txt, /llms-full.txt, and a raw markdown projection of every docs page at /docs/<slug>.md (the quickstart at /docs/index.md). Every docs page gains a copy-page-as-markdown button.

  • New docs pages: Troubleshooting (symptom-first fixes), Data flow & containment (what runs where, the canonical strict data handling definition), and Stream into an Express route. The quickstart rewrites around hello-world-first and the terminal-chunk contract, and the Bands API documents how bands stay current.

  • The console playground now resolves human-in-the-loop pauses. Approval requests and ask_question pauses render as interactive cards (the same unified data-novo-input-* chunks your product consumes) and resume the run on answer; the run status pill shows the waiting state.

  • Console: agent-level cost attribution and structured workspace controls. Billing gains a by-agent breakdown tab; managed-workspace network egress (public / restricted with an allowlist / offline) and lifecycle (idle minutes, retention days) become structured editor fields; the advanced JSON textarea now covers only seed and services.

  • thread_busy now distinguishes held text from consumed approval text. A plain text message that matches a pending approval still returns 409 thread_busy, but now carries details.resolved_interaction_id so clients know the message was consumed as the approval answer and must not be retried. Held follow-ups still use details.queued: true + details.followup_id; if the hold queue is full or over its byte cap, the API returns plain thread_busy and nothing was held.

  • Mid-run steering: messages sent to a busy thread are now delivered into the run, not bounced. A plain-text message POSTed while the thread's run is RUNNING is held (409 thread_busy with details.queued: true + details.followup_id, same as during a pause) and delivered to the agent as its next user turn at the run's next turn boundary, so "actually, make it vegetarian" reaches the agent while the work is in flight instead of after the wrong result is finished. The full held-message lifecycle applies unchanged: listed on Run.queuedFollowups, withdrawable via runs.followups.withdraw(runId, followupId) until delivered, delivery confirmed by one data-novo-followup-replayed chunk per message, and honestly recorded as undelivered on the terminal run if no boundary arrives in time. A message never cancels a run; use runs.cancel to stop rather than steer.

  • Held follow-up messages are now fully observable. A message sent while a run is parked on an approval/question is held and replayed on resume (queue-don't-dismiss); every stage is now visible. The 409 thread_busy response carries details.followup_id alongside queued: true; the run resource lists held messages in queuedFollowups (still present on a run that died while parked, as the record of accepted-but-undelivered messages); runs.followups.withdraw(runId, followupId) (DELETE /v1/runs/:id/followups/:followupId) removes one before it replays; and the stream confirms each delivery with a data-novo-followup-replayed chunk.

  • Run streams now repair AI SDK UI-message framing before cursoring. The hosted stream normalizes text/reasoning frames before assigning public SSE ids. Reconnect semantics are unchanged for SDK consumers: resume with Last-Event-Id, and treat stream.lastEventId as the only ordering/de-dup cursor. Other cursor query parameters are not supported on public stream routes.

0.3.0-alpha.42 - 2026-06-29

  • Opt-in reasoning streaming. A new per-run streamReasoning?: boolean on runs.start and threads.stream forwards model reasoning to the run's public stream as reasoning-delta chunks (a new NovoStreamChunk member). Default false preserves the provider-neutral default: only reasoning-start / reasoning-end boundaries are emitted unless a run opts in. Honored on the root stream and subagent/worker sub-streams.
  • Per-step performance metrics. The data-novo-step-terminal chunk now carries an optional, provider-neutral perf object (stepDurationMs and whole-step stepTps, computed as outputTokens / (stepDurationMs / 1000)) for consumer-side observability. Additive and optional; parse defensively.

0.3.0-alpha.41 - 2026-06-29

  • Unified input-request contract (breaking). Approvals and questions now share one wire and resolve shape: an approval is just an input request whose options are [approve, deny]. The four pause chunks data-novo-tool-approval-requested / …-resolved and data-novo-user-interaction-requested / …-resolved collapse into two: data-novo-input-requested and data-novo-input-resolved. The request's kind ('approval_request' | 'question') and display ('confirmation' | 'select' | 'text') tell them apart. Type guards isNovoToolApprovalRequested / isNovoToolApprovalResolved / isNovoUserInteractionRequested / isNovoUserInteractionResolved are replaced by isNovoInputRequested / isNovoInputResolved. The terminal tool-output-denied chunk and data-novo-task are unchanged.
  • One resolve body (breaking). POST /v1/interactions/:id/resolve no longer branches on kind. The former ResolveApproval / ResolveQuestion split is replaced by one ResolveInteractionBody: { inputResponses?: { requestId, optionId?, text? }[]; cancel?: boolean; reason?: string }. Approve with inputResponses: [{ requestId, optionId: 'approve' }], deny with optionId: 'deny', answer a question by selecting optionId/text per requestId, and cancel with cancel: true.
  • deniedBy removed (breaking). The resolved chunk no longer carries a deniedBy: 'policy' | 'user' label. A denial now surfaces a generic, verbatim reason only, with no attribution to human vs. hook.
  • Follow-up messages queue instead of auto-denying. A chat message sent while a run is parked no longer auto-denies the pause. For an approval pause, a message whose text matches approve / deny (or 1 / 2) resolves the approval; anything else is queued. A question pause never text-resolves: the message is always queued, since a question is answered through the structured inputResponses resolve endpoint. A queued message is replayed to the agent once the gate is answered.
  • Declarative autoAllow. approvals.autoAllow on an agent lists Novo canonical tool names that never require approval, the always-allow analog of a hook returning allow. Listed tools skip the hook and fire immediately.

0.3.0-alpha.40 - 2026-06-29

  • Artifact result-handler refs. Artifact result handlers can now return optional ref, block, or suggested_block_refs fields alongside artifactId/url. Novo normalizes those into model-visible artifact.ref and artifact.block on generated media, explicit workspace exports, browser screenshots, and browser downloads while stream URLs continue to default to durable handler URLs or id-only Novo refs.
  • Tool-result recovery hardening. Oversized list-shaped tool outputs now keep a digest preview plus a deterministic workspace read_file recovery hint when bytes spill. Missing workspace paths can include a deterministic glob recovery hint, and empty non-file-read tool results carry a concise notice instead of disappearing as silent success.
  • Planning guidance tuning. The always-available todo planning tool now more aggressively steers multi-step, multi-file, and list-oriented work into an explicit plan before execution.

0.3.0-alpha.39 - 2026-06-29

  • Tool-error recovery surface cleanup. Retryable precondition failures such as tool_load_required and skill_required are ordinary AI SDK tool-output errors. readNovoToolError(event) recognizes standard tool-output-error chunks and embedded { type: 'tool-output-error' } payloads inside tool-output-available; consumers can correlate toolCallId with the preceding tool-input-* chunk when they need the public tool name.

0.3.0-alpha.38 - 2026-06-29

  • Deferred-tool discovery and load recovery. load_tools can resolve an unambiguous bare operation name such as secret_list to its namespaced MCP or OpenAPI tool, and ambiguous misses include exact namespaced suggestions. Retryable tool_load_required payloads now include machine-readable recovery input for load_tools.
  • Durable load-state guidance and pause lifecycle fixes. Skill and tool loading are documented as durable thread state across later turns, compaction, and resume. Out-of-band approval resolution and run cancellation now repair waiting run status more consistently, and waiting-run cancellation returns an explicit error instead of silently parking when no pending interaction can be terminally cancelled.

0.3.0-alpha.37 - 2026-06-28

  • Required-skill gates for registered tools. Tool servers and HTTP connections now expose requiredSkills on resources, register inputs, and update inputs. Set a skill name or array of names to require the model to load one of those skills before MCP tools or OpenAPI operations can run. For HTTP connections, x-novo-required-skills on an operation overrides the connection default.
  • New context_overflow terminal/error code. NovoTerminalReason and NovoErrorCode now include context_overflow for runs that exceed the selected route's model context window before completion. This is a capacity outcome, not an engine fault, and usage consumed before the cutoff is still finalized on the run.
  • Deferred-tool loading hardening. Registered MCP/OpenAPI tools still defer by default, but the hosted runtime now uses one unified load_tools path, stricter schema-disclosure gates, and deterministic cleanup for extra invented tool-call arguments before managed-cloud validation.
  • Trust-boundary and provider-tool fixes. Provider-executed web results are prompt-injection-fenced before they re-enter managed-cloud history, including web result titles/URLs, and provider-native client tools keep their durable execute handlers after workflow resume.

0.3.0-alpha.36 - 2026-06-27

  • OpenAPI operation-level trust and deferral hints. Specs may mark individual operations with x-novo-trusted: false to keep live external results wrapped even when the connection is trusted, and with x-novo-defer: false | true to override connection-level schema loading. x-novo-trusted: true does not elevate an untrusted connection.

0.3.0-alpha.35 - 2026-06-27

  • Deferred loading for registered tool servers and HTTP connections. Registered MCP tools and OpenAPI operations now defer by default: the model sees each tool's name and description, then loads the full input schema on demand with load_tools. ToolServer, HttpConnection, register inputs, and update inputs add defer?: boolean | null; omit it or send null for the default, send false to keep a small always-used server or connection hot, or send true to pin deferral explicitly.
  • HTTP/OpenAPI connections honor trust and read-only metadata. A connection registered with trusted: true now skips the untrusted-data envelope for its operation output. OpenAPI operations marked with x-novo-read-only: true are scheduled as concurrent-safe, matching the MCP readOnlyHint behavior.
  • Stream and cancellation hardening. Run event streams now retry transient durable-read EIO failures during cold start instead of surfacing a 500, while durable stream-write failures are classified as platform errors rather than upstream model-provider outages. Mid-response user cancellations also leave an interruption marker in the committed turn so the next message does not treat truncated assistant text as complete.

0.3.0-alpha.34 - 2026-06-26

  • New: MANAGED_TOOLS manifest. The SDK now exports the canonical set of managed (cloud-executed) tool names with their classification, so a consumer that gates or renders tool calls can import the contract instead of hand-maintaining a name list that silently drifts when the engine renames or adds a tool. Import from the package root or, for client-safe code, from the pure-data subpath novoagents/managed-tools.
  • First-party trust boundary for workspace and GitHub context. Managed workspace content, including file reads/searches, command output, document_read, and allowlisted GitHub issue/PR/diff/review text, is now delivered as first-party customer context instead of being wrapped as untrusted external data. Browser pages, web fetch/search, default-untrusted HTTP/tool-server output, and third-party connectors still keep the external content boundary. Keep GitHub allowlists and workspace egress policy narrowed to content the agent may rely on and act upon.
  • Cancelled/failed turns preserve visible history. When a run is cancelled or fails after producing assistant output, the hosted runtime now commits that already-streamed output to durable thread history and closes unfinished tool calls before the next turn. Pre-output cancellations/failures still preserve the prior snapshot instead of replacing it with an empty turn.
  • Deny attribution and terminal frames. data-novo-tool-approval-resolved now carries optional deniedBy: 'policy' | 'user' on denials so UIs can label a platform/hook block separately from a human denial. A synchronous approval-hook deny also emits the terminal tool-output-denied frame for the underlying toolCallId, so consumers no longer show those tool calls as pending forever.

0.3.0-alpha.33 - 2026-06-23

  • Worker lineage on approval and interaction surfaces. Worker (subagent) tool calls now carry root-run lineage everywhere a consumer sees them: approval-hook requests, interactions, data-novo-*requested and data-novo-*resolved chunks, data-novo-task, and Novo-hosted MCP/HTTP tool-exec headers. runId identifies the issuing run; read rootRunId for the tree root and workerRef for the worker sub-stream address.
  • Tool approval hook failure semantics documented. Each review is delivered exactly once, bounded by requestTimeoutMs; there is no automatic retry or redelivery. The default onHookError is deny. Return { decision: 'pause' } and resolve later via resolveUrl when a decision needs to be deferred.

0.3.0-alpha.32 - 2026-06-23

  • Subagent dispatch streams are well-formed on the public wire. Internal delegate pause sentinels no longer surface as orphan tool-output chunks that could break AI SDK UIMessage reducers. Worker sub-streams now carry the full dispatch prompt on data-novo-worker-meta.data.prompt; internal routing such as the subagent type stays hidden.

0.3.0-alpha.31 - 2026-06-23

  • Pre-warming to cut first-token latency. New novo.threads.prewarm(threadId?) warms the run path so the first token arrives sooner after idle. The hosted runtime scales to zero, so a thread idle for ~60s+ cold-starts on its next message (several seconds before the first token). Call prewarm when a user is about to send (on input focus, thread open, or first keystroke), targeting a 10–30 second lead. It is a free no-op (no run is created, nothing is billed) and safe to call repeatedly; after any message runs, the thread stays warm ~60s. Maps to GET /v1/threads/:id/messages?warm=1 (the threadId is optional). See the new Pre-warming concept page.

0.3.0-alpha.30 - 2026-06-23

  • New frontier band. A third offered band joins lite and core: frontier is the maximum-intelligence orchestration tier for the hardest jobs, with a cross-checked second opinion on consequential decisions and the highest cost. Select it with band: 'frontier' on an agent, thread, or run; GET /v1/bands now lists it (with per-band strict-data-handling availability). As always, the band is a stable named identity; the routing behind it can improve without changing your API.
  • Band-based usage and reporting surfaces can now return frontier as a band bucket alongside lite, core, and managed_runtime.

0.3.0-alpha.29 - 2026-06-22

  • agents.update replace-semantics, documented. capabilities and the top-level workspace are replace-semantics: send the full desired state and omit a key to disable that capability (e.g. drop github to revoke GitHub). This differs from metadata (key-level merge, null deletes) and policies (per-field patch); the managed workspace's documents/mediaEditing flags are the lone carry-forward exception. Capability edits apply on the next run; cancel the run or revoke the GitHub connection to cut an in-flight run off immediately. Documentation only; no behavior change.

0.3.0-alpha.28 - 2026-06-21

  • Typed reasoning-level override. reasoningLevel is now typed on run inputs for allowlisted eval and experimental routing. Most customers should omit it and keep the band's default reasoning level; non-allowlisted organizations receive validation instead of silently changing serving behavior.
  • Run stream: step boundaries are now emitted; one ordering cursor. The stream now includes the AI SDK step-boundary chunks start-step and finish-step (previously suppressed). A UIMessage reducer uses them to separate the text/reasoning spans of distinct model steps within one turn. This matters because providers reuse stream-local part ids (txt-0, reasoning-0) across steps; start-step adds a step-start part, finish-step adds no visible part. Order and de-duplicate frames by the SSE frame id (RunStream.lastEventId): it is the single per-run cursor, monotonic and strictly increasing, but not necessarily consecutive (internal frames are suppressed), with exclusive (resume-after) Last-Event-Id reconnect. The redundant sequence field on data-novo-* payloads has been removed; stepNumber / frameInStep remain as step attribution (not an ordering key). Never merge a parent run's frames with a worker sub-stream's; each stream has its own independent id space. Do not confuse the SSE frame id with a chunk's content id (e.g. txt-0), which is reused per span.
  • A managed/MCP tool whose backing server is unavailable when its approval is (re)checked now surfaces a tool-output-error tool result (with code / retryable) the agent can react to, instead of terminating the run with an engine_fault and no tool-output frame.

0.3.0-alpha.27 - 2026-06-21

  • Engine-fault terminals: stable reason + structured error.reference. Internal engine failures now finalize with a stable terminalReason (engine_fault, snapshot_unavailable, or run_recovery_reaped) instead of null, so you can map friendly copy. The support reference is now a structured error.reference field (the incident id) rather than a free-text Reference: <id> line appended to error.message. If you parsed the message for the reference, read error.reference instead.

0.3.0-alpha.26 - 2026-06-21

  • BREAKING: fast mode removed. The prelaunch fast-mode controls are gone: the fastMode run/thread option, policies.fastModeDefault, the config.fastMode / config.fastModeServed run fields, and the per-band fast-serving availability block on GET /v1/bands have been removed. Bands now expose only band and strict data handling.

0.3.0-alpha.25 - 2026-06-20

  • BREAKING: event sinks removed. The prelaunch event-sink API has been removed: /v1/event-sinks, novo.eventSinks, Agent.events, AgentEventsInput, EventSink*, and ProductEvent* SDK types are gone. Consume run output and lifecycle through runs.start + runs.stream / streamToCompletion(); use result handlers, approval hooks, environments, and HTTP connections for callback-shaped integrations.
  • BREAKING: data-novo-tool-call removed. Public streams no longer emit the Novo-specific tool-call side channel. Removed NovoToolCallChunk, NovoToolCallStatus, NovoToolCategory, NovoToolExecution, and isNovoToolCall; branch on standard AI SDK tool chunks and the remaining Novo side-channel chunks instead.
  • BREAKING: SDK version header removed. NovoAgents no longer accepts options.version, no longer exposes novo.version, and no longer sends the Novo-Version request header.
  • BREAKING: compact task chunks. data-novo-task now exposes the stable task-card fields only: workerRef, role, status, plus optional label and summary. Routing/debug fields such as sourceToolCallId, streamPath, and arbitrary task metadata are no longer public SDK fields.
  • Credits API. New read-only GET /v1/credits and novo.credits.retrieve() return your balance, auto-reload settings, last reload attempt, and account level with usage; call it as the first step of a billing-status flow.
  • Stream completion hardening. RunFinalResult now includes a customer-safe error when terminal failure detail is available, and streamToCompletion() keeps reconnecting until it observes data-novo-terminal so final text and structured output survive response rollovers.
  • Stream ordering metadata. Novo-specific stream events are typed as NovoDataEvent, with optional sequence, stepNumber, and frameInStep metadata on data for ordering and de-duplication after reconnect.

0.3.0-alpha.24 - 2026-06-19

  • BREAKING: tool renames. Model-facing tool names are aligned with common agent-tool conventions: update_plan is now todo, request_user is now ask_question, and the Skill tool is now load_skill. Update any customer policy or stream-chunk handling that branches on these public toolName values. Internal capability keys are unchanged.
  • BREAKING: list_files removed. Use glob to enumerate workspace files and grep to search their contents; together these cover the directory listing use cases the removed tool served.
  • BREAKING: write_file contract. write_file is now unconditionally create-or-replace and no longer accepts an overwrite parameter. Replacing an existing file still requires reading it first (read-before-write); a brand-new path needs no prior read. Results report honest created / existed flags derived from the runtime's prior-existence probe.
  • Generic web reliability. Generic web_fetch now extracts page content more reliably and treats response content-type casing consistently. Generic web search forwards cancellation to the search provider and filters malformed result URLs before model exposure.

0.3.0-alpha.23 - 2026-06-18

  • Planning is always on. Remove capabilities.planning from agent configs. Every agent can use the planning tool for multi-step work, and those tool calls still stream with category: 'planning'. The model-facing tool was renamed to todo in 0.3.0-alpha.24.

0.3.0-alpha.22 - 2026-06-18

  • HTTP connections. Register OpenAPI-backed tools through novo.httpConnections (register, list, get, update, delete, test) and attach them to agents with capabilities.http.connectionIds. Disabled, missing, or policy-denied connections emit the data-novo-http-connection-unavailable stream chunk and stable http_connection_not_found / policy_denied errors.
  • Structured final output. runs.start and threads.stream now accept outputSchema. When the run completes through the constrained final-output tool, the structured value appears on data-novo-terminal.output and RunFinalResult.output.
  • Canonical shell tool name. Public toolName values for shell execution are now bash across stream chunks, approval hooks, and run resources. The capability key remains terminal.run; customer UI and policy code should branch on toolName: 'bash'.

0.3.0-alpha.21 - 2026-06-18

  • Subagent task labels. Model-supplied task display text is now consistently framed as a label, not a name. Render data-novo-task.data.label as the task title; use workerRef only as the opaque worker-stream address.
  • Support references. Terminal errors caused by observed upstream-provider or infrastructure failures now append a customer-safe Reference: <id> to the error message. Quote that id in support tickets; error.code and error.type are unchanged.
  • Band selection. Public bands now expose both lite and core. core remains the default; use novo.bands.list() (GET /v1/bands) for live availability and strict-data-handling availability.
  • Managed browser control. Managed browser now handles pixel-coordinate fallback internally for canvas and WebGL surfaces. No customer flag is exposed, and browser action-selection tokens continue to bill as normal run inference rather than a separate driver charge.

0.3.0-alpha.20 - 2026-06-16

  • Subagent framing. Public docs and SDK comments now frame subagents as delegated task routing under one root run. data-novo-task SDK types expose the stable task-card fields (label, workerRef, role, status, and summary).
  • Timezone context. Threads and runs now expose the effective IANA timeZone used for Novo's model-visible date/time context. threads.create, threads.update, threads.stream, and runs.start accept timezone overrides.
  • SSE proxy helpers. RunStream.toResponse() and WorkerStream.toResponse() now include Novo identity headers by default while preserving explicitly supplied headers, making server-side SSE proxying easier to trace.
  • Tool-error helpers. Added readNovoToolError(event), isNovoToolError(event), and the NovoToolErrorInfo type so apps can handle tool failures consistently across AI SDK error chunks and returned tool-error payloads.
  • Policy payload types. Exported AgentCreatePolicies and AgentPatchPolicies for callers that type reusable agent policy payloads.

0.3.0-alpha.19 - 2026-06-16

  • Human-in-the-loop timeout. Runs paused on an approval or question now eventually cancel if the human interaction is abandoned past the platform max-park window. The final run has status: 'cancelled', terminalReason: 'interaction_timeout', cancelled pending interactions, and a freed thread. Normal next-day approval flows are unaffected.
  • Console artifact handoff. Console previews and downloads now resolve id-only Novo artifact refs through the authenticated artifact API, so generated media and workspace exports remain usable even when public streams avoid temporary signed URLs by default. Generated-media tool copy now describes the result as an artifact ref instead of implying every result is a direct URL.
  • Remote workspace adapter polish. editFile.replace_all is now part of the environment adapter contract for exact replace-every-match edits, and hosted runCommand dispatch blocks a small set of obvious shell footguns before a command reaches the customer environment.

0.3.0-alpha.18 - 2026-06-16

  • Unified capability surface. The customer capabilities object now uses one family vocabulary across agent config and delegated subagent grants: media replaces the five managed media-generation flags, mcp replaces rawMcp, and documents / mediaEditing move to the managed workspace.
  • Strict media routing. Strict managed media capabilities now resolve per modality to verified strict profiles. A strict run with an enabled media-generation modality that lacks a verified zero-retention, no-training, and US-or-Europe (EU and UK) provider-jurisdiction route fails closed with strict_data_handling_unavailable. Standard media keeps the normal optimized routes. Strict does not claim regional processing or data residency.
  • Strict browser baseline. Baseline managed browser sessions can now run with strict data handling when enabled for the deployment. Browser sessions with strict data handling disable browser-session logging and recording where supported, replace any existing standard browser session, and keep authenticated profiles/file transfer unavailable until their separate storage controls are strict-compatible.
  • Console alignment. New console-created agents now start on the currently offered core band by default, matching the API and SDK default.

0.3.0-alpha.17 - 2026-06-15

Pre-launch baseline. This release collapses the earlier alpha history into the current public contract so new integrations start from one coherent surface.

  • Band selection. lite and core are currently offered bands; core is the default when band is omitted. Use novo.bands.list() (GET /v1/bands) for live availability and strict-data-handling availability.
  • Stable subagent tasks. Agents can delegate independent work to labeled worker or advisor tasks. Novo chooses the appropriate task route; consumers control delegation with capabilities.subagents and normal run budgets.
  • Subagent streaming. data-novo-task chunks describe each delegated task with role, workerRef, status, label, and optional summary. Render label as the UI title and use workerRef only as the stream address. Per-task live transcripts stream through novo.runs.workers.stream(rootRunId, workerRef).
  • Delegation controls. capabilities.subagents is a boolean and remains enabled by default for new agents. A delegated subagent is always a subset of its parent: workers and advisors inherit a read-only baseline (read files and documents, view media, update their plan, use skills, search and fetch the web). Novo may add workspace, shell, media, browser, or MCP authority only when needed and only if the parent already has it. GitHub workflow authority, user interaction, and further delegation are never delegated to a worker or advisor.
  • Streaming reliability. Run streams expose synchronous runId, threadId, and agentId; parsed SSE cursors through lastEventId; reconnect({ lastEventId }); terminal detection through reachedTerminal; and streamToCompletion() for draining long runs across reconnects. RunStream.toResponse() and WorkerStream.toResponse() set X-Accel-Buffering: no for proxy-friendly SSE flushing.
  • Stream taxonomy. The SDK exports guards for every current data-novo-* chunk family, including tool metadata, workspace state, browser sessions, subagent tasks, approvals, user interactions, result overflow, usage, and terminal receipts.
  • Usage ledger. Usage receipts and usage events expose provider-neutral modelLabel values and chargeId join keys. usage.events.list() is the exact debit ledger for agent runs, subagent runs, managed browser, managed workspace, and generated media costs.
  • Managed workspaces. Managed workspaces support filesystem/shell tools, previews, git seeds, services, lifecycle controls, network policy, secret-context projections, GitHub workflows, Office/PDF document tools, explicit artifact export, and oversized tool-result recovery.
  • Workspace base image. Managed shell workspaces include Node.js, npm/npx, git, python/python3, and python3 -m pip. pytest remains opt-in.
  • Managed browser. Browser lifecycle stream chunks are status-only; fetch live-view bearer URLs just in time with novo.browserSessions.liveView().
  • SDK packaging. The SDK remains server-only and has no runtime peer dependencies.