Private provider key pools, print whole conversations, and Entra SCIM fixes
New
18- A second agent harness, behind a flag.
pi(pi-agent-core) now runs in-process in the sandbox alongside OpenCode, selected per project by thepi_harnessfeature flag. It implements abort-after-tool so Quick Queue can stop a turn at a tool boundary, and it enforces the same per-pattern permission rules OpenCode applies. Off unless a project opts in, so nothing changes for existing projects. - Choose which account a connector runs as, per call. A connection now carries the accounts you may run it as, and the account is chosen when the connector is called rather than pinned to the whole session. The connector catalog, the SDK and the CLI all report the available accounts and the pinned default, and
connectors/describeshows accounts instead of only tool counts. - An ambiguous connector call is refused, not guessed. When several accounts are reachable and none is named or pinned as default, the call is denied with
account_requiredinstead of silently picking one — no more mail sent from the wrong mailbox. - Choosing a connector account is discoverable in the CLI rather than a dead end.
- Private provider key pools. Bring several keys for one provider, keep them private or share them with named members, and let each session hold its own key. Sessions fail over to the next key and report the earliest retry time when a pool is exhausted. Gemini and ChatGPT keys pool too, and pooled keys are managed in Models. Pool access is bound to the session owner, and a pool is checked against the model you actually picked.
- Print a whole conversation. Cmd+P prints the full session as a clean document — every message, not one clipped screen of the app.
- Queued prompts you can see and edit. Queued messages show in a list above the composer. Press Up to edit the last one, and Resume picks the queue back up.
- Microsoft Teams install reports what happened. One-click install publishes in the background, lands on Channels with a real status, and offers a retry with the actual reason when publishing fails.
- Astra is available as a ChatGPT subscription model.
- Print a whole conversation. Cmd+P prints the full session as a clean document — every message, not one clipped screen of the app.
- Queued prompts you can see and edit. Queued messages show in a list above the composer. Press Up to edit the last one, and Resume picks the queue back up reliably.
- Private provider connection pools. Bring several keys for one provider, keep them private or share them with named members, and let a session hold its own key. Sessions fail over to the next key and report the earliest retry time when a pool is exhausted. Gemini and ChatGPT keys pool too, and pooled keys are managed in Models.
- Astra is available as a ChatGPT subscription model.
- Project-level provider and model access controls. Owners and admins choose which model providers and which models a project may use, from one model management view that also holds provider links. Kortix managed models sit beside your own providers in the same list, a ChatGPT subscription shows its access beside its credentials, and the picker distinguishes "not shown" from "blocked" so a member sees why a model is unavailable.
- GPT-6 Astra is in the managed catalog. Select
kortix/gpt-6-astrawith image input, tools, and the supported reasoning efforts. Routing, prices, capability limits, and sandbox fallbacks are all in step. - The desktop app always has a way out. The shell has no browser toolbar, so a page without an in-app exit was a dead end. Every such page now has Close, the Go menu has Back (Cmd/Ctrl+[) and Home (Cmd/Ctrl+Shift+H), a renderer crash offers Reload or Go Home instead of an empty window, and the Electron route allowlist now matches the web middleware's exactly.
- Review Center is on for every project. It is no longer behind a feature flag — the routes, registry, contract, web surfaces, CLI, and docs all ship it by default.
- A public App can recognise you.
publicused to mean both "anyone with the link may open this" and "nobody is ever recognised". Now an App you share outside your company still greets your own team, shows them the controls a visitor should not see, and records who acted.
Improvements
30- The
pi_harnesssetting reads correctly in all nine languages. - Internal: the sandbox daemon's timing budgets now tolerate a slow machine during a process respawn, so a correct restart is no longer reported as a failure.
- A connector you have your own accounts for reads as connected, not "needs setup", and the admin connector list now agrees with what each caller can actually reach.
- Connector accounts are per connection instead of a connector-level strategy, and connections the old strategy flag made unreachable are revoked.
- The sandbox daemon's internals were reorganised behind explicit service boundaries, with its HTTP controllers separated from its adapters.
- Faster project boot. New sessions fetch the project from storage instead of cloning it, and start sooner.
- Faster session lists. A project's session list is now a page, not the whole inventory.
- Menus open instantly — menus, popovers, tooltips and the command palette no longer wait to appear.
- Smaller sandbox images, which start faster.
- Git connections are organized per account, with one instance backend and an identity that cannot drift. Verifying with GitHub no longer signs you out, and the new-connection screen always has a way out.
- Faster project boot. New sessions fetch the project from storage instead of cloning it, and start sooner.
- Faster session lists. A project's session list is now a page, not the whole inventory.
- Menus open instantly. Menus, popovers, tooltips and the command palette no longer wait to appear.
- Smaller sandbox images, which start faster.
- Git connections are now organized per account, with one instance backend and an identity that cannot drift.
- Date grouping (Today, This week, Older), filters and search work as before, applied to the sessions you have loaded.
- A new database index serves the paged list, so a request no longer sorts every session in the project.
- Connector activity uses consistent names. Connector calls appear as connector calls.
- Repository access is explicit. Agents now declare whether a session gets the project's files, replacing the older workspace modes. Older API clients keep reading restricted manifests correctly.
- Previews route correctly and set up shared sandboxes in isolation.
- Release checks are more reliable: preview environments use their own database, confirm the running runtime, and wait for completed agent artifacts before asserting on them. They also verify cold terminal wake and session-switch routing, allocate sufficient preview frontend memory, and check Docker readiness.
- One noun: project. The interface said "workspace" while the SDK, CLI, API, routes, manifest, and docs all said "project". Screen copy now says project in every one of the nine languages, each with its own word rather than a find-and-replace. The sandbox
/workspacedirectory, the manifest's per-agentworkspace:boundary, and Slack workspaces keep their names. - Create a project in a specific account. The Switch project menu, already grouped by account, gains a "Create a project in {account}" row for each account where you are an owner or admin, including accounts that have no projects yet. The old global link never said which account it would land in.
- The SSO and SCIM setup wizards work again. Picking a provider did nothing, and Back or the step rail snapped you to the first step with a render loop in the console. Both are fixed, and a browser journey now walks every step of both wizards on every deploy.
- Tunnel file transfers are verified end to end. Binary files sent through the Computer Tunnel are checked by digest at the destination, an approval for one exact file no longer grants its parent directory, permission decisions are serialized so an approve and a deny cannot both win, and orphaned upload tasks are stopped.
- Creating an account is reachable again, and it lands you in the account you created. The control had no live entry point, and the one path that reached it dropped you back where you started. There is now a "Create an account…" row in the workspace switcher, and creating an account opens its first workspace with that account selected.
- Connector categories show their true size. The catalogue counted one page of results and headed every category with "· 1". Categories are now grouped over the complete catalogue on the server, and "View all" filters to the set its heading counted.
- Secret intake forms read better. Field hints written by an agent become real links, every non-form step shares one status notice, and the header no longer runs under the close button.
- Modals opened over modals stack correctly. A modal opened while another was open could render underneath it; it now takes the layer above, and the switch control meets contrast in both themes.
- Session hover cards line up. Sessions carrying a Slack, schedule, or shared marker opened their card inset from the sidebar edge; every row now anchors at the same place.
Fixes
32- Restored the load-balancer response-time alarms required by the Drata DCF-86 control.
- A failed identity check no longer signs you out. A failed
getUserround trip used to end the browser session; it no longer does, and the new-connection screen offers Upgrade when you are at the project cap. - Connector authorization: finalizing a connection that the whole project can use now requires the connections-manage capability, matching the gate the connect step already applied. Previously a role with connector-write but not connections-manage could complete a project-wide shared connection.
- Auto-created connections no longer claim to be the default, and the CLI's account column no longer truncates away the pinned-default marker.
- Stale connector banner copy and a dead connector detail shell removed; the account list renders for every direct provider.
- Microsoft Entra directory sync. Patches apply atomically, large directories paginate, groups survive while a user is inactive or a sign-in session is stale, deactivation and single-member removal behave correctly, and users resolve across the whole directory.
- The gateway retries a slow internal call instead of answering "Gateway unavailable".
- Composer drafts survive session startup, and opening session settings no longer closes itself while the composer takes focus.
- One session lifecycle drain at a time per API task, so queued work is not claimed twice.
- Session attachments are more reliable, and model prices show correctly in the ChatGPT picker.
- Security hardening across session cursors, webhook signing keys, and the remaining high-severity scanner findings.
- Database migrations apply cleanly on staging and production.
- Microsoft Entra directory sync. Patches apply atomically, large directories paginate, groups survive while a user is inactive or a sign-in session is stale, deactivation and single-member removal behave correctly, and users resolve across the whole directory.
- The gateway retries a slow internal call instead of answering "Gateway unavailable".
- Composer drafts survive session startup, and opening session settings no longer closes itself while the composer takes focus.
- Session attachments are more reliable.
- Model prices show correctly in the ChatGPT picker.
- Security hardening across session cursors, webhook signing keys, and the remaining high-severity scanner findings.
- Database migrations now apply cleanly on staging and production.
- Projects with thousands of sessions no longer slow the app down. The session list now loads one page at a time — 50 sessions, with a Load more control — instead of returning every session on every refresh. On a project with 12,617 sessions that is a 46 KB response instead of about 11 MB, and the sidebar was refreshing it every five seconds.
- Opening, sharing, stopping, restarting or renaming a session now works however old the session is. These controls used to look the session up in the full list, so once a project grew past the first page the controls could quietly disappear.
- Terminal opens on a stopped workspace. Opening Terminal requests a wake even before the first shell exists. Connection retries have a deadline and preserve shell output.
- Session switches keep message retries in the right workspace. Missing conversations stop repeated 404 or 410 requests without clearing cached history.
- Sessions keep their own agent. A session could be switched to an agent from a different project after a prompt that named no agent, which removed its access to connectors and the Kortix CLI. Every session now always runs as its own agent, and a session that was affected recovers on its next message.
- The first message on the home screen no longer gets stuck in the composer after a slow start.
- Project pages load cleanly. The project home shows the Kortix mark while it loads instead of a flashing placeholder.
- Session history is saved before a session stops, and responses from the in-sandbox model proxy are no longer returned in a corrupted encoding.
- Admin project list shows each project's own session counts.
- Customize settings show what you saved. After saving an agent or connector setting, a reload could show the previous value for up to a minute.
- Previews open again when you are signed in. A sandbox preview opened from a session (
prod-p<port>-sbx-….p.kortix.com) showed "Sign in to open this preview" even though you were signed in. Sign-in tokens are still issued with the older HS256 signature while the published key set already holds the newer ES256 key. The API already verified those tokens with the auth server, but the preview gate refused them. It now makes the same check, so the preview panel, pasted preview links, and preview WebSockets open for the account that owns the sandbox. A forged or expired token is still refused, and a test now fails if any verifier caller handles these results in its own way. - The sandbox model proxy asked upstream for compressed responses and could not decode them. It now requests identity encoding, so a session on a model that answered with zstd no longer fails its first turn.
- Sending a message no longer makes the transcript jump twice. An idle send moved the view down and then glided it back. The send is now recognised as the working turn, so the view moves once.