github BuilderIO/agent-native @agent-native/core@0.210.0

latest releases: clips-nightly-v0.1.493-0, clips-nightly-v0.1.492-0, v0.1.150-nightly.425...
15 days ago

Minor Changes

  • 6c7c90e: Enable Brain to query Gong with shared organization credentials, keep excluded connection requests settled, and add a bounded CRM-context account-call recipe.

  • 41f86eb: Persist fenced agent execution steps and submission receipts across chat, automation, team, and A2A runs.

  • 108b9d9: Keep MCP audit rows and attribute them correctly. A NUL or other control character in an MCP client's self-reported name or version, or a NUL in any other audit value, is now stored as U+FFFD instead of failing the insert and losing the row, and a failed audit write is logged and reported through captureError while the audited action still completes. Writes made through /_agent-native/actions/<action> with a verified MCP OAuth or connect token now record as mcp by the agent, with the credential's OAuth client id, even when the request also sends the frontend header. An approved A2A tool call that runs after its pause now records the paused task's run, thread, turn and network ids. The audit-log event details show the self-reported client, the OAuth client and the approval, with mcp-client-accepted labeled as unverified.

    Breaking: the signatures of recordActionAudit and recordOrgAdminAuditEvent changed. Both now require an attribution, made only by auditAttribution(ctx) inside an action or routeAuditAttribution(event) in a Nitro route, and a call without one throws AuditAttributionError instead of losing its row. To migrate, move caller, threadId, turnId and runId out of ctx (which keeps only actionName, userEmail and orgId) and pass attribution: auditAttribution(ctx) with the action's run context, or attribution: routeAuditAttribution(event) from a route. Admin changes recorded by hand, such as Restrict personal API keys and the service provider choice, now keep the MCP client, OAuth client and approval instead of storing nulls.

    An A2A call approved on its review page now records approval: "a2a-review", shown as "Approved on the agent action review page", instead of the agent-chat label. Its replay runs outside the paused task's journal again, so an earlier identical call in that task cannot stand in for it. A call's approval (agent chat, an accepted MCP elicitation or the A2A review) and the replay's task ids are held by that call's execution frame, not its run context, so they reach the approved action's own audit rows, including a row it records itself, and not another action it calls, a recursive call, or a later call with a kept context. Two limits remain: a raw (non-defineAction) entry called directly from an action's body shares that action's frame, and a wrapper around an entry's run must keep its ACTION_EXECUTION_KEY (spread the entry) for the action to keep its approval. Without async-local storage no approval is recorded. A service principal's refusal of another call, whether a child action or an agent run started inside an approved action, a dispatcher's approval pause of another call, and its refusal of a call with invalid arguments carry none of the enclosing action's approval; only an action's refusal of itself keeps it, along with that call's reported client, OAuth client, network ids and thread, turn and run ids. An action's approval ends when the promise its run returned settles, not when a stream or iterator it returned is consumed, so a timer, an unawaited write, or work done later while consuming that stream records none of it. The dev action bridge runs each call in its own frame, like the HTTP action route. The action entry exposes no frame-evidence helpers, and request input or ActionRunContext fields never become evidence. Trusted server dispatcher APIs (executeAgentToolCall, runAgentLoop) can still supply approval and attribution. The approval pause's denied row, and the agent loop's row for a call it refuses for invalid arguments, now carry the run id.

  • d0f6950: Audit rows now record which MCP client made a call and the authorization signal associated with it. reportedClientName and reportedClientVersion hold the client's self-reported clientInfo, oauthClientId holds the OAuth client its credential was issued to, and approval (agent-chat or mcp-client-accepted) records the signal for that exact call. agent-chat records a person's approval in agent chat; mcp-client-accepted records that the MCP client accepted its elicitation, which does not verify who responded. The new columns are nullable, older rows are not rewritten, and CSV and OCSF exports include the new fields. CSV exports also prefix formula-like values in every column with an apostrophe before escaping to reduce spreadsheet formula execution risk.

  • fab1c27: Add opt-in MCP output contracts. An action with outputErrorStrategy: "strict" and mcpOutputSchema: true advertises its outputSchema to MCP clients in the shape they receive (array roots wrapped as { items }, open-link fields for linked actions, embed credentials removed, and embed start URLs masked in place as "[hidden embed URL]"), and each structuredContent, including its formats, is validated against it. Schemas whose constraints redaction or the open-link fields could break are refused when the action is defined. Actions without the opt-in advertise no output schema, as before. A strict output mismatch, an output validator that throws, or a contracted result that cannot be serialized now raises ActionOutputContractError (errorCode: "output_contract_violation"). A connection request or stop signal raised while a result is checked stays that signal under any output strategy, but with a framework message that never includes returned values. Both carry effect: "committed" once a write entered its handler, in the call or in one nested in it (even under a read-only action), and effect: "none" otherwise; writes are classified from the call's validated arguments. Committed failures still refresh other sessions over MCP, HTTP, and the in-app agent. The in-app agent reports them as completed side effects, keeps them in the replay journal so a continued turn replays the failure instead of running the write again, and the single-tool result used by A2A carries completedSideEffect on failures too. A connection request raised this way keeps its provider, reason, app, and source in its fields, its message, and HTTP details. The in-app agent, the plan-mode action registry, HTTP action routes, and MCP now prepare each call once, validating its arguments and classifying it, and run exactly that preparation through runPreparedActionCall, which accepts only a call actionCallIntent prepared: approval, plan mode, the unknown-write block, parallel batching, read caching, replay, and the action itself all see the validated arguments, defaults applied, without parsing them again. Preparation stops with the run's abort signal and the tool's deadline. A call whose arguments are invalid fails before any gate, never reaches its handler, and is still audited and tracked, discovered actions included; a connection request or stop that input validation throws still takes its own path in the in-app agent. Preparation reads the validated arguments once, property by property, into a frozen plain-data snapshot and hashes its exact, type-tagged encoding (a Date by its time). The snapshot itself is never handed out: each gate (classification, access, approval, plan mode, audit) and the handler gets its own copy of it, so a value changed after preparation, read differently a second time, or changed by another gate, never runs. Validated arguments that have no such snapshot (a getter or setter, a Map or Set, a class instance, a function) fail the call as invalid before any gate, with or without approval; a direct action.run() call still gets schema validation only. needsApproval now receives a copy of the snapshot, in the in-app agent and over MCP, and an approval binds to its hash: the approval card still shows the call as the model sent it, but a pending approval stores an arguments_hash (a new nullable column on agent_tool_approvals), so one recorded before this release is asked for again, and the approval_required event carries argumentsHash. runAgentLoop accepts a plain approval key only with consumeApproval, which checks the stored hash; a transport that echoes the key back without one binds it with approvalKeyWithArguments, now exported from @agent-native/core/server. Every reuse of a call's outcome keys on that hash instead of the raw input. Each tool_done carries the argumentsHash its call ran with, and a continued turn replays a call only when it recorded a committed effect for that same hash. Reads are deduplicated, cached and reused from the turn's history only for the same hash, so two calls whose defaults prepare differently both run. A call id that more than one call of the turn used, in the journal or the history, names no hash, so none of its results is reused. The zombie-result ledger stores the hash too (a new nullable arguments_hash column on agent_tool_ledger), and an interrupted write recovers only a result recorded for the same hash; any other stops as an unknown outcome instead of running again. Calls recorded before this release have no hash: a write among them still replays when its raw input matches, as before, their reads run again, and an interrupted write stops. Any unknown outcome, a read's included, holds back every later write of its tool, whatever its arguments, in every agent loop of the request. A read is held back only by an unknown outcome recorded for the same hash, in the run, the journal, the history or another loop of the request, never by another call of its action or one recorded without a hash, and cached reads are dropped after any committed or unknown effect. A call whose run recorded that it changed nothing, such as a write stopped before its handler started, is never held back; only a call with nothing recorded is judged by its result in the history, and only a write timed out, interrupted or left without a result there holds back later writes. A call abandoned on an abort or deadline after a write in it entered its handler, including a write nested in a read, records an unknown outcome and recovers its late result from the ledger instead of running again; retrySafe and a write receipt narrow only an action's own write, never one nested in it. A failure's effect speaks only for the call that raised it: raised by a strict read inside a plain action entry declared as a write, it fails that entry as committed, not as a call that changed nothing. Post-turn autosave (onAgentTurnComplete) also runs after a call that failed once its changes were saved.

  • 38ccdb4: Expose a Web-only MCP Fetch adapter at @agent-native/core/mcp/fetch.

  • 38ccdb4: Export a Web Request-to-Response MCP protocol adapter for non-H3 runtimes.

  • 937af16: Surface web search in the first agent tool set, clarify when to use it instead of web-request, and list Builder-managed search as an always-recommended included service in onboarding and Infrastructure Settings.

Patch Changes

  • 7c4669b: Keep app work local by default and reserve A2A for peer-exclusive needs.

  • 9156c9d: The agent and MCP clients can no longer create organization service tokens or change a service principal's policy or lifecycle. These stay available to owners and admins through connect --service-token, the HTTP action routes, and settings.

  • aecef0c: Help the agent find the right tool, and keep runs from ending in an ambiguous state: the system prompt now names every loadable tool, grouped by topic, in its cached prefix, with MCP names delimited as untrusted data; tool-search ranks with BM25 (plural- and stop-word-aware) and suggests close names instead of returning nothing; the agent is told when earlier tool loads could not be restored; unreadable terminal events no longer let an older outcome hide an unknown newer one; and a failed inline claim during background dispatch is retried and logged instead of looking like a worker claim.

  • e48e8b5: Let agents list organization members and invite people. list-organization-members returns members and, for owners and admins, pending invitations. invite-organization-member sends one member invitation through the same path as Settings > Members, asks the user to approve every call in chat and over MCP, and cannot grant admin. Invitations sent from settings or by an agent are now recorded in the organization audit log for owners and admins.

  • 578c558: Agents now see the details a fail() attaches. The in-app agent and MCP tool results add an Error details: {...} JSON line after the message and error code, and MCP results also carry structuredContent.error with the message, code, and details, unless the tool advertises an output schema. Details are redacted like error messages and capped at 2,000 characters; when they run over, small top-level entries are kept and the rest are listed as omitted. An action that told agents to read details.importId (or any other detail) now works as written.

  • 880bc72: Expose the agent run start time to final-response guards for stable relative-date checks.

  • 41f86eb: Serialize turn cancellation with execution lease claims so a worker cannot retain a live lease after its run is aborted.

  • 41f86eb: Project run lifecycle fields from durable SQL state in AgentKit thread snapshots.

  • 3be3035: Brighten the Learn more link on shared signup pages.

  • c498fae: Add resolveWorkspaceConnectionsForApp, which returns every workspace connection the request user may use for an app in one pass: one connection list, one user-scope filter, and one grant list.

  • e9b8f80: Keep production evals on the shared chat path, safely retain failures, and keep provider error details private.

  • 7028ea5: ChatGPT plan status lists saved accounts again on a request that is not a local loopback, still without reading the Labs preference there.

  • 067e3b8: Explain why email sign-in and verification links require a confirmation click.

  • 26bd989: Show saved subscription accounts in unsupported OAuth status responses while preserving loopback privacy.

  • 7028ea5: A collaborative document connection stops polling and pushing presence while it waits to be disposed, so switching away from a document that is then deleted no longer requests it and gets 404s.

  • 7028ea5: A collaborative document no longer starts a second polling loop when the window regains focus, the tab becomes visible, or sync restarts while a poll is still in flight, and a poll request that never answers is abandoned after 15 seconds so polling resumes.

  • 41f86eb: Recover a missing queued-message projection from its durable submission receipt before promotion.

  • 9c277b7: Advertise reviewed MCP tool annotations for framework tools. The bash, edit, and write coding tools and the set-service-principal-lifecycle and set-service-principal-policy actions are destructive, and ask-agent is destructive and open-world.

    run-code and web-request now advertise readOnlyHint: false, destructiveHint: true, and openWorldHint: true over MCP, and OAuth tokens need mcp:write to list or call them. Both are still read-only to the in-app agent. More generally, MCP treats a read-only action as a write when its plan-mode effect can classify a call as a write, or when it declares readOnlyHint: false. That covers the scope check, the derived hints, ask-app-only write filtering, and directory-profile validation. Dev discovery now keeps an action's planMode, so its plan-mode effect also reaches the in-app agent in dev, as it already does in production.

    MCP clients of a dev server see new hints for the files it discovers as tools. Before, every discovered tool advertised readOnlyHint: false, destructiveHint: false, and openWorldHint: false, whatever the file declared. Now a discovered action advertises the mcpAnnotations it declares. One that declares none advertises destructiveHint: true and openWorldHint: true, or readOnlyHint: true and openWorldHint: true if it is read-only; a file wrapped as a command-line tool counts as a write. These framework defaults live in the action entry's new mcpAnnotationDefaults, so mcpAnnotations holds only hints an action declared itself. Production catalogs do not include discovered files.

    Export the framework action loader list so contract tests can load every entry strictly.

  • 208f4e3: Keep forwarded and unresolved loopback status requests from reading saved ChatGPT accounts.

  • dd132f7: Reorganize the Chat docs into the five-page structure (Overview, Features, Talk to the Agent, Cross-App Use, Developer Guide). Fold "Your First Feature" into the Developer Guide and redirect the old page.

  • 3215556: verifyScopedAgentAccessToken no longer accepts scoped agent-access tokens minted in the older format that embedded the resource id in the payload. Links and approval emails minted before the compact format shipped (7 days at most) stop verifying, and the caller sees a normal failed verification. signShortLivedToken and verifyShortLivedToken are unchanged.

  • 7ade653: Links in an extension that open a new tab (target="_blank", Cmd/Ctrl/Shift-click, or middle-click) are now opened by the host page, http/https only and with noopener, instead of as popups of the sandboxed iframe, so pages like HubSpot records load instead of rendering blank. The extension iframe's sandbox and window.open are unchanged.

  • 41f86eb: Improve durable run recovery by reusing completed action receipts and recording terminal metadata atomically.

  • 8e84193: Tag first-run onboarding analytics events with an experiment id and variant so setup-page tests can be compared in Analytics. Persist the assignment so first-run outcome events retain the variant across reloads. Add isAgentNativeAnalyticsConfigured() so experiments can skip users whose events have no analytics destination.

  • 208f4e3: Preserve app routing when extension shells open external links and avoid reading local-only OAuth settings on non-loopback status requests.

  • 774af36: MCP tool text that is cut at 2,000 characters now states the original and shown lengths and says the result is incomplete, and names the action's paging inputs when it is read-only.

  • Release all public npm packages with a patch version bump.

  • c19512c: Hide embed start URLs and their tickets from direct MCP tool results when they are nested in another URL, used as an object key, or sit beside a ticket field, including a ticket beside _agentImages, and in error messages, action links and image notes. Direct results are read as JSON before anything else, so a toJSON method or getter cannot add a start URL after the check. When anything a call produced holds a start URL, including a proxied tool's _meta or a URL an action's link builds, the call's text and structuredContent drop every ticket field and replace any whole string that echoes that ticket, raw or escaped, and _meta leaves out any entry that carries it other than the widget's embed start and source. A result the check cannot fully read, because it is not JSON data (such as one holding a BigInt) or holds a string escaped more deeply than the check reads, is withheld whole. A write, told by its effect rather than by whether it sends change events, still reports success and records its change, its resource hint read from the result as the action returned it, as it does when building its response fails after it ran, and its widget still gets any session it minted; a read fails. An action with an MCP output contract instead fails, read or write, with its output_contract_violation error, which tells the model not to retry a write, and a write still records its change; such a result that is not JSON as returned (a function or symbol at its root, a toJSON that returns undefined, or a BigInt or cycle in an image entry) now fails that way, where it used to be sent as {} or lose the image. An error that cannot be read, such as one whose getter throws, becomes a fixed failure instead of a protocol error. A value an action's schema, gate or handler throws that cannot be classified is replaced, before any caller sees it, by a plain error that says so, so MCP, HTTP and A2A routes, the agent loop and the audit log all get an ordinary failure, and what the call did follows its write evidence. Server warnings that print an error or an output schema's issues hide any start URL in them. The log and error capture of an input schema that cannot be sent to a provider hide its reason and path together when either names the start route, never call a method on one that is not text, and no longer attach the original error. Converting an action's input schema for the MCP tool list or the agent's tools no longer throws: whatever reading or converting it throws leaves that action out with a reported reason, any start URL in it hidden, instead of failing the whole list. A widget write that produced nothing is still flagged isError, so the host mounts no empty widget, but it says its change was saved and records it. A result is classified once, before anything else can fail, as isMcpActionResult reads it: a proxied tool's text, raw, raw.isError and then the wrapper's other own enumerable fields each get one classification read, so an inherited, hidden or getter flag counts, and neither a field's getter nor the later JSON copy of raw can change the status. A start URL in those fields, such as the tool's input, still hides the ticket. Each of those fields is copied as JSON on its own, so one named toJSON is never called, and one that is not JSON data withholds the result. The response is built from those parts, so a directory projector cannot clear a reported failure, and the change marker's resource hint reads the same result. A status that cannot be read is never taken for success: the response says so, with isError, and a write still records its change. A failure after the action ran is described once, checked whole, its error code included, against everything the call had built by then, directory projections and links included. That one description goes to the response and, when the call is recorded as an error, to MCP analytics. One that cannot be checked becomes a fixed sentence, which for a result that is not JSON data says so. Error capture gets that sentence, and the checked description of a write that is reported as completed. An error from before the action returned, thrown by the action or by its approval request, has a start URL in its message and type hidden in the response and MCP analytics alike. An action's link is built from the result as the action returned it, and checked with the rest of the response. Images are checked against everything the call built, and one that carries a credential is left out whole; image bytes are not scanned while the call's credentials are collected. A ticket field is read in any escaping the check decodes. Shared MCP action calls hide echoed tickets the same way, and report an unreadable result as a result-stage failure. App-only tools such as create_embed_session now return their start URL in _meta["agent-native/embedStart"] instead of structuredContent, and the embed widget reads it from there.

  • ca67d21: Advertise MCP tool input schemas that pass the Anthropic, OpenAI and Gemini schema rules Core pins. A root anyOf, oneOf or allOf is flattened into one object, and the schema description lists the argument sets it combined. Hand-written JSON schemas get the same keyword stripping as Zod schemas. A typeless const or enum gets an explicit type taken from its values, so Codex no longer narrows { "const": 1 } to a string. A string const is advertised as a one-value enum, which Gemini honors, and maxItems moves into the description, because Gemini refuses a forced call to a large bounded array. Gemini's enum holds strings only, so an enum that lists a number, boolean or null keeps its type and lists its values in the description instead; one value becomes a const. Over MCP every rewrite only widens what the schema accepts, boolean subschemas included. The in-app copy does too, except that it admits no array directly inside an array, because the in-app Gemini adapter drops $ref, so nothing there can recurse. Actions still validate calls against their own schema.

    A schema reference that does not resolve, including one that names an inherited property such as #/$defs/__proto__, now fails with a named error instead of disappearing when its branch is flattened. References spelled as encoded pointers or $anchor names are rewritten to plain pointers first, and one into a oneOf branch or a not, which stripping rewrites or removes, is moved into root $defs so it still resolves; an $id below the root, a non-local $ref and $dynamicRef are refused. A const that its own enum does not list, a const or enum with no value of the position's type, such as { "type": "string", "enum": [1, 2] }, or an empty enum, anyOf or oneOf, is refused the same way, since that position accepts no value, and so is a root schema no object satisfies, such as an allOf with a string branch, which flattening used to advertise as an object schema. A root $ref whose target is an object schema counts as one. These checks read JSON Schema 2020-12, the dialect MCP assumes, so defineAction now asks schema libraries for 2020-12, which Zod emits with $defs and prefixItems tuples. A schema is checked when its $schema is absent or the official 2020-12 URI. One that names another dialect, such as draft-07, or an unknown URI, gets none of these checks beyond an object root. It is offered stripped and without $schema: the stripping still types a typeless const or enum and describes a non-string enum as above, but its root is not flattened, a string const stays a const, and maxItems stays. A property or definition named __proto__ or constructor keeps its own entry through every rewrite. In the in-app agent and over MCP, an app action with such a schema is left out of the tool list and logged as an error, so the other tools keep working. So is an action whose input schema is not an object, which over MCP used to fail the whole tool list, including a false schema, which the in-app agent used to take as no schema. Each converter reads an input schema once, into a plain copy that it checks and converts, and never edits the schema or a schema library's output in place. A getter, a value JSON cannot hold such as NaN or a BigInt, a cycle, an object that is not plain, or one whose reads throw leaves the action out with the position and reason, instead of being checked as one value and advertised as another. Only an action whose schema library emits no JSON Schema is still offered as taking any object; when finding or running the library's emitter, a check or the conversion throws, defineAction keeps the reason with the tool it builds, and the action is left out, also when it is copied with that tool. Another action defined with the same schema is judged by its own tool. Other surfaces that describe actions, such as A2A agent cards, the action manifest and WebMCP, tool-search summaries and the framework prompts, still list such an action with its stripped schema or any-object parameters. Over MCP the instructions do not name it either, and tools/call answers it as an unknown tool. A remote MCP tool gets the same checks, and one that fails them is held back when its server's tools are listed: the server stays connected with its other tools, and its integration status names the unusable tool and why. Reconnecting the server from Integrations lists its tools again over the same connection, so calls already running on it are not interrupted. Those lists run one at a time per server, so an older answer cannot replace a newer one. When that list fails at the transport, because the server refuses it over HTTP, as it does once an OAuth grant is revoked, or cannot be reached at all, the server is left as a failed connect leaves it: its tools are no longer offered, a call to one fails because the server is not connected, and Reconnect reports it disconnected. Choosing Reconnect again connects it from the start, which starts OAuth for a server whose OAuth grant was revoked. A list the server answers with a JSON-RPC error, or one that times out, keeps the connection and the tools listed before, and Reconnect answers with the error.

  • 3d6a9d3: Run MCP action calls through one internal execution step for scope, approval, the action itself, and embed-ticket redaction. Direct MCP tool results are unchanged.

  • 7028ea5: The local Design bridge's preview auth shim no longer rewrites a missing src/href into /null?previewToken=…, so appending an image or script that has no source yet stops logging a 404 in live previews.

  • 4bed5e7: provider-api-docs now follows redirects (301, 302, 303, 307, 308) when it fetches a public documentation page, up to 5 hops, instead of failing with the redirect status. Each hop's Location must be an http(s) URL that passes the same private-address check as the first URL before it is fetched, and docs fetches still send no credentials. A redirect loop, more than 5 hops, a redirect without a Location, or a blocked hop fails with a provider_docs_redirect_* error code that names the reason. The result's request.finalUrl reports where the content came from, and links in the extracted content resolve against it. Credentialed provider-api-request calls still never follow redirects.

    Provider responses without a Content-Length header now stop reading at the byte cap, so a large or endless body can no longer force an unbounded allocation or hold the request open. Such a response reports sizeIsLowerBound: true, and its truncation messages say "at least" that many bytes. Docs redirect hops are not read at all.

  • 41f86eb: Keep stale run projections and late execution receipts behind every active execution fence.

  • d0e3828: Keep trusted first-session reads visible while the scoped cache binds, then clear them on sign-out.

  • ebf0bdf: Factory feedback guidance preserves Slack reactions, uses the connected Slack integration, and avoids routine post-merge reporter follow-ups.

  • 461d53c: provider-api-request now treats a listed set of read-only POST endpoints as reads: GA4 Data API reports, Search Console search analytics and URL inspection, BigQuery query dry runs, HubSpot CRM search and batch reads, Gong call and stats reads, Notion search and queries, PostHog queries, Jira search, Prometheus queries, Google Calendar free/busy, and Google Sheets data-filter reads. A failed report or search no longer stops the run with write_tool_outcome_unknown, so the agent can correct its arguments and try again. Any other POST is still a write.

  • 41f86eb: Defer queued run interruption until the current model or tool work reaches a safe boundary.

  • 0cfbd4d: Include the MIT license text in the published package.

  • ed34578: Open clicked external links from sandboxed extension frames in a separate browser tab, with the frame handshake nonce kept out of the extension URL.

  • d0e3828: Accept feature flag delegations when the receiver verifies the organization scope from the signed domain claim.

  • 7337569: Resolve personal scope for local ChatGPT plan access and explain the requirement in settings.

  • 7664dc3: Keep text motion previews on the shared timeline when staggered units extend past the stored duration.

  • 23f6f12: Stop collaborative document polling when the final subscriber leaves, and restart it if the document is mounted again during the connection reuse window.

  • e19fce1: Better Auth's framework migrations now belong to a store recorded in _an_store_migrations, so the release step runs a single migration runner. The signing-key expiry migration runs at most once per database; existing databases import their Better Auth history instead of re-running it.

  • dd55f83: The org, context-xray, observational-memory and automation trigger-event migrations now belong to framework stores recorded in _an_store_migrations. Existing databases import their history instead of re-running it; hosted apps that do not migrate at release keep their previous bookkeeping for these lists.

  • deb1f92: Local development, tests and self-hosted servers now record framework store migrations in the _an_store_migrations ledger, so each migration runs once per database instead of on every process start. Hosted requests still never write the ledger.

  • 429e5fe: Twelve framework migration lists that ran only in the release step (tool approvals, OAuth tokens, chat-thread schema, observability, agent runs, harness sessions, usage alerts, remote devices, identity SSO, workspace connections, automation runs and scheduler health) now belong to the stores that own their tables and are recorded in _an_store_migrations. Existing databases import the history those lists already recorded, so nothing re-runs.

  • bf54dc3: Fresh databases now install the framework schema from a generated snapshot in one transaction instead of replaying every migration since the first release. A fresh release drops from about 2,500 SQL statements to about 680, and a first pnpm dev boot gets the same snapshot. Existing databases keep upgrading step by step.

    Databases that already ran the audit log's baseline migration now also get the MCP client and approval columns (reported_client_name, reported_client_version, oauth_client_id, approval) through a new audit migration, instead of only fresh databases.

  • 7664dc3: Make React text playback honor Text Motion v2 animation direction, unit order, overlap timing, and whitespace settings.

  • 0f1c4b0: Add Sigma OAuth connections for user-scoped Analytics access.

  • d0e3828: Serialize organization domain assignments, distinguish missing from ambiguous matches, and refuse unresolved signed domain claims. Keep transient domain lookup failures on the retryable identity-verification path.

  • 7028ea5: A chat thread that its first run has not saved yet now reads as a typed { absent: true } state for clients that send the x-agent-native-thread-absence: typed header, so a new chat's first snapshot and title saves no longer log 404s before creating the thread.

  • 69b873f: Keep attachment submissions available without Web Crypto and reject leased run writes that lack an execution fence.

  • 41e43db: Use the plain web search label in onboarding setup.

  • 55c4d37: Preserve app-prefixed embedded HTML pages and PCK renderer payloads in Netlify workspace static routing and function exclusions while keeping the app root HTML shell under server routing.

  • Updated dependencies [41f86eb]

  • Updated dependencies

  • Updated dependencies [0cfbd4d]

  • Updated dependencies [69b873f]

    • @agent-native/agentkit@0.210.0
    • @agent-native/recap-cli@0.5.75

Don't miss a new agent-native release

NewReleases is sending notifications on new releases.