--- title: Changelog | Tabstack description: All notable changes to the Tabstack SDK and API, newest first. --- ### **Packages:** - [`@tabstack/sdk`](https://www.npmjs.com/package/@tabstack/sdk) (TypeScript) - [`tabstack`](https://pypi.org/project/tabstack/) (Python) --- Subscribe to the [RSS feed](/changelog.xml) --- **Latest breaking change: [2.0.0](#200--2026-01-16).** Deprecated MCP server tool schemes were removed. If you upgrade across 2.0.0, [review the migration below](#200--2026-01-16). --- []() ## 2.6.1 - 2026-05-05 Added **Endpoint-specific timeouts.** `/automate` and `/research` now apply a 600 s (10 min) default timeout at the SDK level. This overrides any shorter global timeout set on the client. Long-running automations and research tasks will no longer be cut off. **`task:trace_context` event.** The `/automate` stream now emits a `task:trace_context` event as the first event after task acceptance (before `task:started`). Its payload carries `traceId`, a W3C 32-character hex trace ID you can use to deep-link into Cloud Trace, Cloud Logging, or your own distributed tracing UI for the run. ``` for await (const event of stream) { if (event.event === "task:trace_context") { console.log("Trace ID:", event.data.traceId); } } ``` **Custom headers via environment variable.** Set `TABSTACK_CUSTOM_HEADERS` to a newline-separated list of `Key: value` pairs to inject default headers into every request without code changes. ``` TABSTACK_CUSTOM_HEADERS="X-My-Header: value X-Another: value2" ``` **Scroll browser action.** Automation agents can now scroll pages during task execution. Appears as an `agent:action` event with `action: "scroll"`. Docs - `extract.json` null behavior clarified: if a field in your schema cannot be populated from the page, the response returns `null` for that field. The call does not fail. - Quickstart standardized to `TABSTACK_API_KEY` as the environment variable name. --- []() ## 2.6.0 - 2026-04-24 Changed **`AutomateEvent` is now a fully typed discriminated union.** `complete`, `error`, and `done` are first-class members of the union. Handle them with explicit `case` branches. The prior pattern of catching them in a `default` branch with manual casts is no longer necessary and should be removed. ``` for await (const event of stream) { switch (event.event) { case "task:completed": console.log(event.data.finalAnswer); break; case "complete": console.log(`Done in ${event.data.stats.durationMs}ms`); if (!event.data.success) console.error(event.data.error?.message); break; case "done": break; case "error": console.error(event.data.error.message); break; } } ``` **`complete` event data fields:** - `finalAnswer: string | null` - the agent’s result - `stats: { durationMs, iterations, actions, startTime, endTime }` - run metrics - `success: boolean` - `error?: { code, message }` - present when the agent aborted **`error` event data fields:** - `error: { code: string, message: string, timestamp: string }` - `timestamp` is ISO-8601 - `success: false` --- []() 2.5.0 - 2026-04-22 · Fixed Fixed **`/research` default mode is `fast`.** The SDK documentation incorrectly listed `balanced` as the default. The actual default is `fast`. If you need balanced mode, pass `mode: 'balanced'` explicitly. []() 2.4.0 - 2026-04-09 · Added Added **Interactive mode.** `client.agent.automateInput(requestId, { fields })` added. When an automation task emits an `interactive:form_data:request` event and needs human-supplied field values to continue, call this method with the `requestId` from the event and the field values. Pass `cancelled: true` to abort the interaction. ``` for await (const event of stream) { if (event.event === "interactive:form_data:request") { const data = event.data as { requestId: string }; const response = await client.agent.automateInput(data.requestId, { fields: [{ ref: "email", value: "user@example.com" }], }); } } ``` See the [interactive mode guide](/guides/interactive-mode/index.md) for the full pattern. **`geo_target` added to `extract.json`, `extract.markdown`, and `generate.json`.** Pass an ISO 3166-1 alpha-2 country code to proxy the request through a matching geo. (Was already available on `/automate` since 2.1.0.) ``` const data = await client.extract.json({ url: "https://example.com/pricing", json_schema: { type: "object", properties: { price: { type: "string" } } }, geo_target: { country: "GB" }, }); ``` []() 2.3.0 - 2026-03-12 · Added Added **`effort` parameter** added to `extract.json`, `extract.markdown`, and `generate.json`. Controls the speed vs. capability tradeoff: | Value | Time | Use when | | ------------ | ------- | -------------------------------- | | `'min'` | 1-5 s | Static pages, fastest possible | | `'standard'` | 3-15 s | Default, balanced reliability | | `'max'` | 15-60 s | JS-heavy SPAs, complex rendering | ``` const data = await client.extract.json({ url: "https://example.com", json_schema: { type: "object", properties: { title: { type: "string" } } }, effort: "max", // full browser rendering }); ``` []() 2.2.0 - 2026-02-11 · Fixed Changed Fixed - Memory leak with abort signals in the HTTP client resolved. Relevant if you cancel in-flight requests. - Abort listener was removed too early in some edge cases. Fixed. Changed - MCP server package renamed. Update your MCP server configuration if you use the Tabstack MCP server directly. []() 2.1.0 - 2026-01-30 · Added Added **`/research` endpoint.** `client.agent.research({ query, mode?, fetch_timeout?, nocache? })` for multi-source autonomous web research with cited answers. Always streams `ResearchEvent` via SSE. ``` const stream = await client.agent.research({ query: "What are the top TypeScript ORM libraries in 2025?", mode: "fast", // 'fast' (default) | 'balanced' }); for await (const event of stream) { if (event.event === "complete") { console.log(event.data.report); console.log(`Sources: ${event.data.metadata.totalPagesAnalyzed}`); } if (event.event === "done") break; } ``` --- []() ## 2.0.0 - 2026-01-16 **Breaking changes to the MCP server.** Read this before upgrading across 2.0.0. Breaking **MCP server deprecated tool schemes removed.** If you were passing tool scheme flags when invoking the MCP server, update your command to one of: Terminal window ``` node /path/to/mcp/server # or npx @tabstack/sdk ``` Code mode is the only supported scheme going forward. Added - MCP server: `intent` parameter added to the execute tool. - SDK package renamed to `@tabstack/sdk`.