From 45f2b0e30f1ac89e1f83dd9b16e8d6ef57ad789d Mon Sep 17 00:00:00 2001 From: "tembo[bot]" <208362400+tembo[bot]@users.noreply.github.com> Date: Tue, 18 Aug 2026 16:35:43 +0000 Subject: [PATCH] release: cut v2026.8.3 Co-authored-by: Ry <4283+ryw@users.noreply.github.com> --- CHANGELOG.md | 26 ++++++++++++++++++++++++++ docs/src/content/docs/changelog.md | 26 ++++++++++++++++++++++++++ web/src/lib/docs-content.ts | 2 +- 3 files changed, 53 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2dc52cf..799d15e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,32 @@ they are no longer release versions. Phase scope now lives in ## [Unreleased] +## [v2026.8.3] — Dashboard load-time fix, duplicate-migration CI guard — shipped 2026-08-18 + +### Fixed +- **The workspace dashboard took seconds to render.** Every visit blocked on a + full GitHub reconciliation of open improvements before any database query + ran: one PR fetch per open improvement — unbounded, so a large backlog drew + secondary rate-limit 403s whose answers were then discarded — plus two calls + to GitHub's ~30 req/min search endpoints, issued back-to-back. The scan now + runs its three paths concurrently, caps PR fetches at 8 in flight, and + re-runs at most once a minute per workspace. Improvement PR state is + correspondingly at most a minute stale: a PR you merged moments ago can take + that long to show as `Merged`. +- **The dashboard's 30-day activity chart loaded one row per run.** The + workspace-wide trend spans every agent, so it shipped the entire 30-day run + set to the web tier to run-length-encode in JavaScript. The encoding now + happens in SQL and returns one row per band the chart actually draws. + +### Changed +- CI fails a pull request when two migrations share a version number — the + defect that made v2026.8.1 unable to boot. + +### Dependencies +- Routine Dependabot bumps across web, api, docs, and CI actions (better-auth, + cron-parser, vite, eslint-config-next, `@types/node`, thiserror, base64, + Astro, github/codeql-action). + ## [v2026.8.2] — migration 0069 collision fix, per-user MCP OAuth, durable Pydantic runs — shipped 2026-08-17 ### Added diff --git a/docs/src/content/docs/changelog.md b/docs/src/content/docs/changelog.md index 173c915..9069ab2 100644 --- a/docs/src/content/docs/changelog.md +++ b/docs/src/content/docs/changelog.md @@ -19,6 +19,32 @@ they are no longer release versions. Phase scope now lives in ## Unreleased +## v2026.8.3 — Dashboard load-time fix, duplicate-migration CI guard + +### Fixed +- **The workspace dashboard took seconds to render.** Every visit blocked on a + full GitHub reconciliation of open improvements before any database query + ran: one PR fetch per open improvement — unbounded, so a large backlog drew + secondary rate-limit 403s whose answers were then discarded — plus two calls + to GitHub's ~30 req/min search endpoints, issued back-to-back. The scan now + runs its three paths concurrently, caps PR fetches at 8 in flight, and + re-runs at most once a minute per workspace. Improvement PR state is + correspondingly at most a minute stale: a PR you merged moments ago can take + that long to show as `Merged`. +- **The dashboard's 30-day activity chart loaded one row per run.** The + workspace-wide trend spans every agent, so it shipped the entire 30-day run + set to the web tier to run-length-encode in JavaScript. The encoding now + happens in SQL and returns one row per band the chart actually draws. + +### Changed +- CI fails a pull request when two migrations share a version number — the + defect that made v2026.8.1 unable to boot. + +### Dependencies +- Routine Dependabot bumps across web, api, docs, and CI actions (better-auth, + cron-parser, vite, eslint-config-next, `@types/node`, thiserror, base64, + Astro, github/codeql-action). + ## v2026.8.2 — migration 0069 collision fix, per-user MCP OAuth, durable Pydantic runs ### Added diff --git a/web/src/lib/docs-content.ts b/web/src/lib/docs-content.ts index 31d4e8b..b429cb4 100644 --- a/web/src/lib/docs-content.ts +++ b/web/src/lib/docs-content.ts @@ -42,7 +42,7 @@ export const DOCS: Record = { "changelog": { "title": "Changelog", "description": "Every notable change to Tembo Agent Studio, by release.", - "body": "All notable changes to Tembo Agent Studio. Format loosely follows\n[Keep a Changelog](https://keepachangelog.com/en/1.1.0/).\n\n**Versioning:** releases use a year.month [CalVer](https://calver.org/) tag plus\na release counter — `vYYYY.M.N`. `YYYY.M` is the year and month; `N` increments\nonce per release within that month and is **not** the day of the month (the\nearliest 2026 tags happened to line up with the date, but it's just a counter).\nThe `0.1`–`0.4` entries below are phase numbers from\n[`ROADMAP.md`](./ROADMAP.md), which remain the *construction* milestones;\nthey are no longer release versions. Phase scope now lives in\n[GitHub Issues](https://github.com/tembo/agent-studio/issues?q=is%3Aissue+label%3Aenhancement).\n\n## [Unreleased]\n\n## [v2026.8.2] — migration 0069 collision fix, per-user MCP OAuth, durable Pydantic runs — shipped 2026-08-17\n\n### Added\n- **Per-user OAuth for the TAS MCP server.** Claude Web, Claude Desktop, and\n other hosted MCP clients can now discover TAS OAuth metadata, register\n dynamically, complete S256 PKCE, select a workspace, and receive refreshable\n tokens bound to the signed-in user's live membership and role. Existing\n `tas_` API keys remain\n supported for Claude Code and scripts.\n- **Durable Pydantic runs.** Pydantic executions now persist their immutable\n launch envelope and checkpoint typed message history at every model/tool node.\n Runs interrupted by an API or host restart resume from the last acknowledged\n checkpoint, preserve the original run clock and completed-step usage, and\n show a **Resumed** indicator on run detail. Cargo AI and legacy runs remain\n explicit interruption failures because they have no safe replay boundary.\n\n### Fixed\n\n- **v2026.8.1 could not apply database migrations.** That release shipped two\n migrations both numbered `0069` (`workspace_user_secret` and\n `instance_admin`), so the api recorded one and crashed applying the other —\n and afterwards no version could boot against the touched database.\n `instance_admin` is now `0070`. Upgrading to this release is the fix; if a\n v2026.8.1 api already ran against your database, first check\n `SELECT description FROM _sqlx_migrations WHERE version = 69;` — if it says\n `instance admin`, run `UPDATE _sqlx_migrations SET version = 70 WHERE\n version = 69;` once before upgrading (the file was renamed with identical\n content, so the recorded checksum already matches). If it says\n `workspace user secret`, or there is no row 69, no manual step is needed.\n- **Chat-to-PR tasks could drift to the wrong repository.** Tembo agent tasks\n now carry an explicit scope block pinning them to the workspace's connected\n agents repo and default branch, so session context mentioning other repos or\n prior PRs no longer redirects the change.\n- **Claude showed the Railway logo for the TAS connector.** The MCP initialize\n response now advertises Tembo's display name and a public PNG icon, the icon\n directory bypasses the session gate, and `/favicon.ico` provides a fallback\n for clients that use conventional origin favicon discovery.\n\n## [v2026.8.1] — Password management for email/password instances, in-app instance admins, personal Tembo identity — shipped 2026-08-04\n\n### Added\n- **Lost / reset / change password on email/password instances.** TAS is\n SMTP-free, so recovery is admin-driven: a workspace admin generates a\n one-time reset link (1-hour expiry) from the member's detail page and\n shares it out-of-band; the link lands on a new public `/reset-password`\n page. Signed-in users change their own password under Settings →\n Account. Both revoke other sessions. None of this renders when an OAuth\n provider is configured — credentials live at the identity provider there.\n- **Instance admins managed in-app.** Instance Settings now lists and edits\n instance admins (stored in the database, unioned with the\n `INSTANCE_ADMIN_EMAILS` env bootstrap); the sign-up gate honors both\n sources, so admin changes no longer require a redeploy.\n- **Personal Tembo identity with workspace fallback.** Chat-to-PR authoring\n can use a per-user Tembo API key (Settings → Tembo), falling back to the\n workspace key — PRs and sessions attribute to the person, not the shared\n workspace identity.\n- **Built-in run date/time tool.** Every Pydantic agent can call\n `get_run_datetime` without adding a connection. It returns the stable run-start\n instant and local date/time fields for a requested IANA timezone, giving\n scheduled agents a reliable basis for relative windows and date-based dedup.\n\n### Fixed\n- **Invitations now resolve on email/password instances.** Credential\n sign-ups always carry `emailVerified=false` (no IdP, no SMTP), and the\n invite-to-membership step required a verified email — so invitees could\n sign up but landed workspace-less. On email/password instances the\n invite-gated sign-up itself is the authorization, and invites now resolve;\n instances with an OAuth provider keep the strict IdP-verified check.\n\n### Changed\n- **Continuous deploys now cover all Tembo-managed instances.** The internal\n pipeline that tracked `main` on the dogfood box now fans out per-instance\n (each with its own Railway project token) — self-hosted customer\n instances remain pinned to release tags like this one.\n\n## [v2026.7.4] — Inbox reading view for digests, markdown context + run links, quieter Slack threads — shipped 2026-07-24\n\n### Added\n- **Inbox item detail: markdown context + run link.** Context fields that\n contain Markdown (agent digests) now render formatted instead of as raw\n text, and the header links to the run that produced the item.\n- **Newsletter-style reading view for text-only inbox items.** Any text-only\n context (the `{ text }` shape `produce_inbox_item` stores for plain-string\n contexts) now renders as an unboxed full-width document at reading size\n (18px/1.6) with no CONTEXT/TEXT chrome — the markdown sniff only picks the\n renderer (Markdown vs pre-wrap), so table-only markdown can no longer fall\n back to the boxed fields view. GFM tables are recognized and wide tables\n scroll horizontally. Structured contexts keep the boxed labeled-fields view.\n- **Links rollup on inbox items.** The Links section moves below the content\n and collapses behind a \"Links (N)\" disclosure past 5 entries, so a digest\n citing 20 sources no longer opens with a wall of links while short triage\n lists stay fully visible. `produce_inbox_item`'s descriptions now steer\n producers to inline markdown sources for narrative digests.\n\n### Fixed\n- **Slack: untagged thread replies no longer trigger the which-agent menu.**\n A plain reply inside a bot DM thread (e.g. answering a daily brief with\n `Y`) used to post the \"Tell me which agent to run…\" menu on top of any\n custom listener already answering that thread. Untagged thread replies are\n now left to the thread's listener; explicit `@agent` mentions in a thread\n still launch their agent, and plain top-level DMs are unchanged.\n- **Internal deploy CI: Railway GraphQL errors now fail the job.** Railway\n reports failures in-band with HTTP 200, so `curl -f` never tripped — an\n expired plan left the deploy step green while deploying nothing.\n\n## [v2026.7.3] — pydantic-ai 2.x runner, WebSearch run + agent-change dispatch fixes, catalog batch 3 — shipped 2026-07-20\n\n### Added\n- **Native MCP catalog batch 3: 136 more providers.** Harvested from the\n official MCP registry (54k entries swept), the claude.com/connectors\n directory, and community remote-MCP lists; every endpoint live-probed\n (MCP `initialize` → `/.well-known/oauth-protected-resource` →\n auth-server metadata → `registration_endpoint`) on 2026-07-18:\n - **TAS-managed DCR (123):** sales/GTM (Outreach, Salesloft, ZoomInfo,\n Lusha, Hunter, Instantly, Crossbeam, Harmonic, Chili Piper, Day AI,\n Clarify, Staircase AI), support/CX (Zendesk, Help Scout, Gorgias, Plain,\n Lorikeet, Unthread, Enterpret, Dovetail, Missive), meetings (Otter.ai,\n Grain, Krisp, Circleback, tl;dv), finance (Ramp, Brex, Mercury,\n Expensify, Navan, Carta, Digits, GoCardless, Mercado Pago), market\n intelligence (PitchBook, Morningstar, CB Insights, Quartr, Daloopa,\n Consensus), HR/recruiting (Gusto, Deel, Ashby, Workable, Metaview,\n Indeed, Udemy Business), compliance/e-sign (Vanta, Drata, SignNow),\n productivity/design (Figma, Miro, Lucid, Productboard, Aha!, Shortcut,\n Todoist, Teamwork, Calendly, Superhuman Mail, Craft, Mem, Gamma, Pitch,\n Eraser, Jotform, Typeform, SurveyMonkey, Egnyte), marketing/content\n (Mailchimp, Customer.io, Ahrefs, Semrush, Cloudinary, Contentful,\n Sanity, Wix, WordPress.com, GitBook, Mintlify, DeepL), dev/infra\n (GitLab, Supabase, Netlify, Heroku, Buildkite, Grafana, New Relic,\n Honeycomb, incident.io, Rootly, BugSnag, LaunchDarkly, PlanetScale,\n Prisma Postgres, InstantDB, Algolia, Statsig, Postman, Semgrep, WorkOS,\n Stytch, Mux, Knock, Lovable, Retool, Telnyx, Jam, Globalping), data/AI\n (Airbyte, MotherDuck, Monte Carlo, Atlan, Hugging Face), and\n automation/web (Zapier, Make, IFTTT, Exa, Tavily, Firecrawl, Apify,\n Bright Data).\n - **Bring-your-own OAuth app (12):** DocuSign, Xero, Front, Smartsheet,\n MongoDB Atlas, CircleCI, Chargebee, BigQuery (Google manual client,\n like Gmail), Ironclad, Harvey, Tableau, Shopify.\n - **API token (1):** Render (API key as Bearer, like GitHub).\n - Agent Library categories now recognize the new providers, and the\n long-tail **ATS / recruiting**, **HRIS**, **E-signature**, and\n **Survey** categories flip to connectable.\n - Not added (with reasons): per-tenant instance-scoped servers\n (Salesforce, Snowflake, Databricks, ServiceNow, NetSuite, Glean, dbt,\n Elastic…), OAuth `client_credentials`-only (Plaid), unauthenticated /\n docs-only servers, and vendors with no hosted server (Workday,\n Rippling, Okta, Snyk, Perplexity, Loom, Fivetran).\n\n### Fixed\n- **WebSearch agent runs on Claude no longer fail with a 400.** Anthropic now\n routinely pauses long server-tool turns (`stop_reason: pause_turn`), which\n pydantic-ai 1.x replayed malformed — every run of a `WebSearch`-capability\n agent died with *\"`web_search` tool use … without a corresponding\n `web_search_tool_result` block\"* from 2026-07-16 on. The bundled runner is\n now pydantic-ai **2.13.0**, which continues paused turns natively. Also\n drops the sequential-tool-calls default for WebSearch agents on Anthropic\n models (the API rejects `disable_parallel_tool_use` combined with the new\n web_search tool's programmatic tool calling).\n- **Agent-change submissions work again.** Tembo CAP renamed its public task\n route from `/public-api/task` to `/public-api/session` (2026-07-16) with no\n alias, so every chat-edit / improve / create dispatch since then failed with\n *\"invalid request path\"*. TAS now calls the new endpoint.\n- **Agent-change dispatch errors are self-describing.** The REST/MCP path\n reported CAP failures as an opaque `(http)`; it now includes the upstream\n HTTP status and response body.\n\n### Changed\n- **Runner: pydantic-ai 1.102.0 → 2.13.0.** Spec `instrument: true` and\n ScaleDown compression now attach as pydantic-ai capabilities\n (`Instrumentation` / `ProcessHistory`); behavior is otherwise unchanged.\n- **Rust OAuth-origin allowlist is now generated from the web catalog.**\n `api/src/native_oauth_allowlist.rs` is produced from `MCP_PROVIDERS`\n (`web/src/lib/mcp-providers.ts`) by `npm run gen:allowlist`, replacing the\n hand-maintained duplicate (~360 lines of consts + tuples) in\n `native_oauth.rs`. The allowlist-sync vitest is now a staleness check on the\n generated file instead of a per-provider drift detector — the failure mode\n where a catalog entry lands without its Rust twin (the Dialed regression)\n is eliminated rather than just alarmed on. No behavior change: the generated\n table is semantically identical to the old hand list (184 origins).\n\n## [v2026.7.2] — Native MCP catalog expansion, connection search, Zoom, inbox delete — shipped 2026-07-15\n\n### Added\n- **Large native MCP catalog expansion.** ~30 more hosted OAuth MCP providers\n verified via live discovery (Anthropic knowledge-work-plugins +\n `/.well-known` probes):\n - **TAS-managed DCR:** PostHog, Stripe, Vercel, Canva, ClickUp, Close, Sentry,\n Mixpanel, Granola, Dropbox, Webflow, Cloudflare, Neon, Cal.com, Klaviyo,\n PayPal, Square, Airtable, Railway, Resend, Hex, Pendo, Similarweb, Datadog,\n Common Room\n - **API token:** GitHub (PAT), X (App-only Bearer)\n - **Bring-your-own OAuth app:** Slack, Gong, Box, PagerDuty, Zoom\n (`mcp.zoom.us`; `client_secret_basic` supported for manual token exchange)\n- **New connection search.** Landing page search spans Native MCP, Composio\n toolkits, and manual credentials — jump straight to a provider. Composio is\n ranked and styled as **last resort** when a native option exists (Recommended\n vs Fallback sections, badges, quieter type card).\n- **Native MCP picker table.** Connections → New → Native MCP is a searchable,\n filterable, sortable table (category + auth filters, Connect link).\n- **Delete dismissed inbox items.** On the Inbox **Dismissed** facet, multi-\n select and permanently **Delete** (owner-scoped). Active facets still mass-\n **Dismiss**; *Done* stays unselectable.\n\n### Fixed\n- **Run detail header cost** now prices prompt-cache halves (0.1× read / 1.25×\n write) instead of undercounting when caching engages — aligned with the step\n footer.\n\n## [v2026.7.1] — Agent Library, knowledge-work skills + 9 MCP providers, Sonnet 5 default, new Tembo mark — shipped 2026-07-08\n\n### Added\n- **Agent Library.** A browsable catalog of ~124 ready-made starter agents\n across work areas (Sales, CS, RevOps, Finance, Legal, Data,\n Product/Engineering, IT…), ranked **connection-aware** so the starters you\n can actually run — given what you've connected — lead. Clicking a starter\n pre-fills the New Agent form and the existing Tembo Coding Agent flow turns\n it into a spec + PR. Starters live as one-file-per-starter YAML read at\n runtime, composed from shared archetype prompts. Public + in-app docs page.\n- **Nine more native MCP providers.** Notion, Intercom, Atlassian (Jira),\n Asana, monday.com, Guru, Fireflies, Amplitude, and Apollo — all confirmed\n Dynamic Client Registration, so they're TAS-managed connections with no\n per-customer OAuth app and are enabled by default in the picker. Harvested\n from Anthropic's\n [knowledge-work-plugins](https://github.com/anthropics/knowledge-work-plugins)\n connector catalog (batch 1).\n- **Browse + install Anthropic knowledge-work skills.** The Skills install\n page now surfaces that repo's ~95 Agent Skills as a catalog — filter by\n work area, search, install with one click. Their `SKILL.md` format is\n exactly what TAS already mounts, so agents pick up role-specific domain\n expertise alongside the matching library starters.\n- **Agent Skills documented for the Coding Agent.** `/for-agents` guidance\n now covers authoring and consuming Agent Skills.\n\n### Changed\n- **New agents default to Claude Sonnet 5** (`anthropic:claude-sonnet-5`).\n Model guidance flips the \"start on Opus, then downgrade\" playbook — Sonnet 5\n is agentic enough to be the starting point, with Opus 4.8 / Fable 5 reserved\n for the hardest work. Sonnet 4.6 is retired from examples, docs, the sample\n agent, and the CAP prompt.\n- **New Tembo T mark.** The app and docs favicons (and the README badge) swap\n the old elephant-trunk logo for the new blocky-T mark, with cache-busting so\n stale favicons refetch.\n- README refreshed to clarify setup and the project overview.\n\n### Fixed\n- Dropped the redundant \"Create an agent that handles this task:\" prefix on\n library-seeded agent requests.\n\n## [v2026.6.29] — More MCP providers + confidential/instance connect, Clerk triggers, schedule-from-description, graceful drain — shipped 2026-06-30\n\n### Added\n- **Four more native MCP providers.** Amplemarket, Clay, Avoma, and Metabase\n join the native-MCP catalog and connect in a couple of clicks.\n- **Confidential & instance-based MCP connect.** Two new connection shapes widen\n what TAS can authorize: **confidential Dynamic Client Registration** for\n providers that require a confidential OAuth client (this unblocked Avoma), and\n **instance-based providers** where the user supplies part of the server URL —\n e.g. your own Metabase host. Both keep the SSRF guards of the existing flows.\n- **Optional API key on a native-MCP connection.** A connection can now carry a\n supplementary API key alongside its OAuth token (some providers gate write\n actions behind a scoped key the MCP token can't grant), with a per-provider\n note explaining **why** and **which scopes** are needed.\n- **Trigger agents from Clerk webhooks.** Inbound Clerk events (Svix-signature\n verified) can fire an agent; the webhook signing-secret UI is now\n provider-agnostic so other signed-webhook sources slot in.\n- **Scriptable run cancel.** `POST /api/v1/runs/[id]/cancel` kills an in-flight\n run from the API, complementing the in-app Stop button.\n- **Auto-create a schedule from the agent description.** When you create an agent\n whose description names a recurring schedule (\"every weekday at 9am\"), TAS\n parses it and creates an enabled automation alongside the agent. Conservative —\n prose that merely mentions a time doesn't trigger one.\n- **Timezone-aware automations (DST-correct).** Automations store an IANA\n timezone and the scheduler evaluates each cron in that zone, so a wall-clock\n schedule tracks daylight saving. The form gains a timezone picker (defaulting\n to your browser zone); existing automations keep firing in UTC.\n- **Agents-owned on the Team dashboard.** Each member row shows how many agents\n they own, with a count of unowned agents so nothing falls through the cracks.\n- **Copy button on the Definition tab** and **expandable tool-call errors** in\n the run step timeline.\n\n### Changed\n- **Graceful shutdown.** On deploy/restart the api now **drains in-flight runs**\n before exiting instead of killing them mid-execution.\n- The new agent file is committed next to the user's request, and inbox guidance\n softens the OAuth-token-for-REST advice (an item now also accepts string\n context).\n\n### Fixed\n- **Prompt-cache token accounting.** Stopped double-charging cached prompt tokens\n and fixed live per-step input tokens under-reporting mid-run.\n- **Connect flows.** Amplemarket and Metabase reject the auto-appended\n `offline_access` scope — no longer requested; an unset auth mode is treated as\n DCR so those connections stay editable; runs are registered before the\n subprocess spawns (no orphaned \"running\" rows on a crash at startup).\n- **Sidebar.** Failing-agent alerts are scoped to your own runs (a teammate's\n failure no longer nags you), and the \"Action needed\" header no longer lingers\n over an empty section once its cards are dismissed.\n- **LinkedIn (and any manual-credential) logo** now renders on the connections\n list, detail, and picker instead of a generic glyph.\n\n## [v2026.6.28] — Agent web search, inbox triage + links, self-documenting tool reference — shipped 2026-06-25\n\n### Added\n- **Agent web search.** Agents can now actually search the web by declaring\n `capabilities: [WebSearch]` — it maps to pydantic-ai's provider-adaptive web\n search (native on Anthropic/OpenAI, local fallback otherwise). The capability\n was documented but silently ignored by the runner before.\n- **Self-documenting tool reference.** The `/for-agents` reference now publishes\n each native-MCP tool's full **parameter schema** (name / type / required /\n description), not just a one-line description — so an agent author (and Tembo\n CAP) can discover a tool's exact arguments. The `tembo-agent-studio` reference\n is served without a token (its tools are TAS's own public API), and an instance\n can opt the whole reference public via `TAS_FOR_AGENTS_PUBLIC`.\n- **Inbox links.** An agent can attach a clickable **Links** list to one inbox\n item via `links: [{ label, url }]` on `produce_inbox_item` — e.g. the top 10\n Linear tickets behind a single triage task. Links are also **auto-extracted**\n from an item's proposed text (Markdown + bare URLs) and context payload, so the\n list populates even when the agent didn't set the field. http(s)-only, deduped,\n capped.\n- **Faster inbox triage.** Resolving an item now **advances to the next** one to\n review (with an \"N more in your inbox\" counter); the index gains **multi-select\n mass-dismiss**; and **Dismiss** is now always available on the item detail page\n (previously hidden when the agent supplied one-click options).\n\n### Changed\n- **Tool caches auto-refresh.** Every native-MCP + Composio connection's cached\n tool catalog now re-syncs on each deploy (and daily) instead of requiring a\n manual Connections → Refresh — so new/changed tools (and their schemas) appear\n on their own. Throttled so restarts don't re-storm provider APIs.\n- **Agent ownership on first run** and the marketing landing copy refresh.\n\n### Fixed\n- **Pending agent-create ghost cards.** A chat-to-create whose commit didn't\n carry the reconcile marker could sit \"Pending\" forever and couldn't be\n dismissed; creates now auto-reconcile once the agent file lands in the repo,\n and Dismiss clears direct-commit creates too.\n- **Inbox checkbox hit area** — a near-miss on the row checkbox no longer opens\n the item instead of toggling selection.\n\n### Security\n- **CodeQL batch** — least-privilege workflow `GITHUB_TOKEN`, complete\n markdown-table escaping, and log-injection hardening.\n- **ReDoS fix** — the inbox link-extraction trailing-punctuation trim no longer\n uses a backtracking-prone anchored regex on agent-supplied URLs.\n\n## [v2026.6.27] — Stop a run, security hardening, agent owners + Definition history — shipped 2026-06-23\n\n### Added\n- **Stop a running run.** A red **Stop run** button on the run detail page kills\n an in-flight (queued/running) run: it transitions to a dedicated new\n `cancelled` status (distinct from `failed`, so killed runs stay out of failure\n dashboards/badges) and the api SIGKILLs the run's subprocess. Operator+ only.\n- **Definition tab now shows every version.** The agent's Definition tab renders\n the live draft plus every promoted stable version (switchable), and a\n **History** section listing every commit of the spec file on GitHub — short\n hash, date, and author — each linking to that version on GitHub.\n- **Agent ownership.** A repo-committed agent with no owner is auto-assigned to\n the person who first runs it (chat-created agents already had an owner), so the\n Mine/Starred views and Locked/Fork rules attribute correctly.\n- **Marketing homepage for the docs site.** The docs root is now a restrained\n splash landing page (replacing the bare \"Redirecting…\"), including a FAQ on how\n TAS differs from Claude Managed Agents and Claude Cowork, and a live GitHub\n star count in the header.\n\n### Changed\n- **Orphaned runs are reconciled on api boot.** A run executes as an in-memory\n task owning a subprocess, so any run still `queued`/`running` when the api last\n stopped (crash, deploy, restart) was orphaned and hung in `running` forever.\n The api now marks such rows `failed` on startup with a clear reason. (Durable,\n resumable execution remains the larger [#170](https://github.com/tembo/agent-studio/issues/170) effort.)\n\n### Security\n- **Invites are honored only for IdP-verified emails** ([#47](https://github.com/tembo/agent-studio/issues/47)) — an OAuth sign-in\n whose provider didn't assert `email_verified` no longer auto-joins a workspace\n by matching a pending invite.\n- **OAuth state now has a TTL** ([#46](https://github.com/tembo/agent-studio/issues/46)) and the **permissive CORS layer was dropped\n from the api** ([#48](https://github.com/tembo/agent-studio/issues/48)) — it served only bearer-gated server-to-server routes,\n so the open CORS was needless attack surface.\n- **Stopped logging CAP prompt payloads** ([#44](https://github.com/tembo/agent-studio/issues/44)) and **gated audit-log export on\n admin** ([#43](https://github.com/tembo/agent-studio/issues/43)).\n- Overrode `hono` to `>=4.12.25` to clear Dependabot alerts ([#206](https://github.com/tembo/agent-studio/pull/206)).\n\n### Fixed\n- **Inbox privacy** — the Tasks Inbox was showing every member's items to all\n members. Items are now scoped to their owner (the run's acting user, or the\n human filer), with reads, the sidebar badge, and mutations all owner-scoped.\n\n### Dependencies\n- Routine Dependabot bumps across web, api, docs, and CI actions\n (better-auth, lucide-react, cron-parser, tower-http, Astro, `@types/node`,\n `@tailwindcss/postcss`, actions/checkout).\n\n## [v2026.6.26] — Agent stars + forking, unified Automations, Locked agents — shipped 2026-06-20\n\n### Added\n- **Per-agent \"Locked\" toggle.** Workspace admins can lock a governed agent\n (e.g. regulated drafting): its in-app edits — Chat to edit, Improve, Fork, and\n correction/learning capture — are removed and its Versions / Activity /\n Learning history is hidden, so it changes only through direct repo PRs. Set on\n the agent's Settings tab (admin-only) and audited on change.\n- **Unified agent Automations tab.** An agent's Automation tab now lists its\n schedules, event triggers, and inbound webhooks in one sortable, filterable\n table (matching the workspace Automations list), with a **New automation**\n type picker (Schedule / Event trigger / Webhook) in place of the separate\n inline forms.\n- **Agent visibility — stars + forking.** Star agents (☆ on each row) to curate\n a personal list; the agents page defaults to **Mine + Starred** (agents you own\n or starred) with a **View all** toggle, so big teams aren't staring at\n everyone's agents. And **Fork** any agent into your own editable, owner-prefixed\n copy (`sales-gen` → `ryw.sales-gen`) — no name collisions, owned by you, shares\n the original's tools module until you change it. New `agent_star` table; agent\n names may now carry one optional `.` owner prefix.\n- **One-command sandbox bring-up** — `./scripts/dev-up.sh` writes a dev `.env`\n (email/password sign-in, random secrets), boots Postgres + api + web via Docker\n Compose, and seeds an instance-admin login you can use immediately. Plus a\n `tembo.nix` (Rust toolchain on top of the sandbox's preinstalled Node/Docker)\n so [Tembo sandboxes](https://docs.tembo.io/features/sandbox/overview) and\n snapshots have what the build needs.\n- **Local sample agents for dev** — when a workspace has no connected GitHub\n repo and `TAS_LOCAL_AGENTS_DIR` is set, agents load (read-only) from that\n directory instead of GitHub. `docker-compose.yml` mounts the repo's `./agents`\n and enables it by default, so the bundled samples list, view, and **run** with\n no repo or PAT. Chat-authoring / improvements (which open PRs) still need a\n connected repo.\n\n### Fixed\n- **Composio connection name mismatch** no longer triggers a false \"Action\n needed\" prompt (or a failed run): when an agent pins a toolkit slot by a name\n you authorized under a different one, your single active connection for that\n toolkit is now used regardless of the declared name — matching native-MCP.\n- **Local sample agents** render without a connected repo — the workspace home\n and agent pages no longer redirect to repo onboarding when\n `TAS_LOCAL_AGENTS_DIR` is set.\n\n### Security\n- **Encrypted secrets are bound to their row** (AES-GCM AAD), so a ciphertext\n blob can't be moved to another row and still decrypt. Non-breaking (versioned\n blob; existing ciphertext keeps decrypting). Covers workspace secrets, native\n + Composio connection credentials, OAuth client secrets, Slack tokens, and\n webhook / API-key tokens.\n- **Workspace favicon route** now requires membership — unknown slugs,\n unauthenticated, and non-member requests all return the generic default,\n closing a workspace-existence probe.\n\n### Documentation\n- **Example Agents** — a new docs page of copy-paste, connection-agnostic\n agent-creation prompts (email triage, ticket/issue roundup, CRM tasks, daily\n task list). Paste one into chat-to-PR authoring and it adapts to whatever\n you've connected — generating one agent per matching service.\n\n## [v2026.6.25] — Email + password quickstart sign-in, docs refresh — shipped 2026-06-19\n\n### Added\n- **Email + password quickstart sign-in.** When no OAuth provider (Google /\n Microsoft / OIDC) is configured, the login screen now offers email + password\n — so a fresh instance is reachable with zero OAuth-app setup. Sign-up stays\n gated to `INSTANCE_ADMIN_EMAILS` / invited emails, and configuring any OAuth\n provider turns email/password off automatically (OAuth becomes the path).\n\n### Documentation\n- **New Tasks Inbox guide** — how items are produced, the action buttons that\n act in the source (Complete / Reply / Send and Archive / Archive), snooze,\n terminal dismiss, the learning loop, and the producer-side fields for agent\n authors.\n- **Fuller agent-spec reference** (Authoring agents) — documented\n `model_settings`, `request_limit`, `retries`, `instrument`, and `skills`.\n- **Connections** — the native-MCP catalog (TAS-managed vs bring-your-own OAuth\n app), the **Manage providers** setup for HubSpot/Gmail, and Gmail's Google\n Developer Preview gate.\n- **Introduction + README** — now describe the full *definition → run → act\n (human-in-the-loop Tasks Inbox) → adapt* loop, and correct the principle to\n **\"every change is a commit\"** — a pull request by default, or a direct commit\n in YOLO mode (the old \"every change is a PR\" predated YOLO delivery).\n- **Changelog page** — cleaner release headers (no brackets / shipped-date) and\n an H2-only \"on this page\" TOC.\n- **Roadmap** — pruned ideas that have since shipped (adaptive corrections loop,\n Tasks inbox, direct-commit / YOLO mode).\n\n## [v2026.6.23] — Tasks Inbox actions: act in the source — shipped 2026-06-18\n\n### Added\n- **Act on inbox items in their source system** — option buttons now run the real\n action on click, not just clear the item:\n - **Complete** a task in Dialed / Attio / Linear via a generic **native-MCP\n inbox executor** (the producing agent declares the tool + args; it runs on\n the clicking user's connection).\n - **Send / Send and Archive / Archive** for Gmail via a **Composio inbox\n executor** — Send replies and keeps the thread in your inbox, Send and Archive\n replies then files it out, Archive files without replying. Replies use an\n editable suggested draft (the LinkedIn pattern).\n- **Linear native-MCP provider** (`mcp.linear.app`, TAS-managed OAuth) — the\n Linear tasks agent moved off Composio onto it.\n- **Gmail native-MCP provider** — a manual / bring-your-own Google OAuth app (like\n HubSpot), with in-app setup guidance on Connections → Manage providers (redirect\n URI, the Gmail-specific API + scope steps, docs link). Google currently gates the\n Gmail MCP server behind its Developer Preview program, so Gmail can alternatively\n run through Composio.\n- **`gmail-tasks` email-triage agent** — surfaces your top starred/important emails\n into the Inbox (capped, deduped) with a deep link and a suggested reply.\n- **Deep links on inbox items** — an \"Open in ↗\" link to the underlying\n Dialed task / Linear issue / Attio record / email thread (new `url` field).\n- **Snooze + Dismiss escapes** on inbox items, with per-agent control over which\n clear actions appear (e.g. Gmail uses Archive instead of Dismiss).\n\n### Changed\n- **Inbox source shown as a provider logo** in the list + item detail (was the raw\n lowercase word); the technical Type column/badge is gone.\n- **Sidebar Inbox badge stays live** — polls the active count so items an agent\n produces in the background appear without a manual refresh.\n- **Task agents surface source content faithfully** — `dialed`/`attio`/`linear`/\n `gmail` run with ScaleDown off (no lossy compression of data they copy verbatim)\n and prioritize their queues (Linear: triage → in-review → in-progress → todo →\n backlog; Gmail: starred first; etc.).\n\n### Fixed\n- **Dismiss is terminal** — a re-running agent can no longer drag a dismissed item\n back into the Inbox (the reopen-on-new-activity path now skips dismissed rows).\n- **Inbox actions tolerate a connection-name mismatch** — fall back to your sole\n active connection of the provider type when the agent's declared name differs.\n- **Learning-mode checkbox no longer reverts after Save** — it revalidated the\n wrong tab and never re-synced to the saved value.\n- **ScaleDown** now treats prior history as context and the new turn as the query\n (per the API), and safely compresses bulky prior tool outputs.\n- **LinkedIn thread list pagination** uses the provider's real opaque cursor.\n\n## [v2026.6.22] — ScaleDown prompt compression + agent cost/run — shipped 2026-06-18\n\n### Added\n- **ScaleDown prompt compression.** Optionally route bulky prompt/context through\n [ScaleDown](https://scaledown.ai) to cut frontier-model tokens. Set a ScaleDown\n key under Settings → LLM Providers, then opt in per agent with `scaledown: off |\n prompt | aggressive`. `prompt` compresses the static instructions once\n (cache-friendly); `aggressive` also compresses bulky history blocks each turn,\n memoized so Anthropic prompt caching keeps working. Best-effort end to end — any\n ScaleDown failure falls back to the original text, so it never fails a run.\n Savings show on the run detail (\"5.1K → 1.8K tokens\").\n- **Avg cost/run on the agents table.** A new sortable column showing each\n agent's average estimated USD cost over its costed runs in the last 30 days.\n- **`request_limit` agent-spec field** — cap an agent's model requests per run\n via Pydantic AI `UsageLimits` (#183).\n\n### Changed\n- **Automations table gained Run as.** The unified automations table now shows\n (and filters by) which user's credentials each automation runs as.\n- **Run page polls less aggressively.** The run-detail auto-refresh now backs off\n (2s → 15s) instead of a fixed 1-second tick, so long runs don't trigger a full\n server re-render every second.\n\n### Fixed\n- **Sidebar \"Action needed\" failure card.** Uses the proper\n `sentiment-negative-subtle` surface (no more muddy brown in dark mode) and a red\n CTA instead of an orange-on-red clash.\n\n## [v2026.6.21] — Tasks Inbox + LinkedIn triage agent — shipped 2026-06-17\n\n### Added\n- **Tasks Inbox.** One workspace queue of everything your agents are waiting on\n you for, pinned to the top of the sidebar with a live count badge. Each item\n carries the agent's proposed action — you review, edit, and submit. Search,\n filters, sortable columns, friendly (non-JSON) context rendering, and success\n toasts on every action.\n- **Snooze.** Move an item out of the inbox for a set duration; it returns on its\n own — or sooner if a newer reply lands on the thread.\n- **Agents work the inbox too.** It's a tool surface over Native MCP and the\n `/api/v1/inbox` REST API (`produce_inbox_item`, `list_inbox_items` with\n search / filter / sort, plus claim / propose / complete) — humans and agents\n act on the same queue as peers.\n- **Action menus + one-click execution.** A producer can attach a set of typed\n options (a reply with an editable draft, or one-click actions), one marked\n recommended. The inbox renders them as buttons and *runs* the action on click\n (e.g. send or archive on the source system), not just records it.\n- **Self-learning loop.** What you change versus what the agent proposed is a\n signal. Agents in \"learning mode\" aggregate signals and open a single\n improvement PR per cycle, rather than one per correction.\n- **LinkedIn inbox-triage agent.** Pulls recent LinkedIn threads into the Tasks\n Inbox, drafts a reply from the full thread, and offers one-click **Send**,\n **Send + Archive**, or **Archive**. Keeps the queue capped at a few open\n threads (tops up, never piles on), skips threads you've archived / handled /\n snoozed, and pages back for fresh ones when the recent list is all handled.\n- **Manual-credential connections.** Connect services with no OAuth (e.g.\n LinkedIn) by pasting a few values alongside setup instructions, stored as\n workspace secrets. \"New connection\" is now a four-type picker — Native MCP /\n Composio / Manual credential / Secret.\n\n### Changed\n- **Automations is one full-width table.** Schedules, event triggers, and\n inbound webhooks now live in a single searchable / filterable table instead of\n a three-tab split. \"+ New Automation\" opens a type picker (Schedule / Event\n trigger / Webhook), mirroring New connection.\n- **Shared DataTable across every list.** Agents, runs, connections, inbox,\n automations, and the rest share one table component — consistent row hover,\n whole-row click, and sortable headers everywhere.\n- **Skills page restructured** into a table of installed skills with a top-right\n \"+ New Skill\" picker and a clickable per-skill detail view.\n\n### Fixed\n- **Inbox sidebar count updates the moment you act on an item** — the workspace\n layout is revalidated on submit / dismiss / execute / snooze.\n- **Runner:** import `AnthropicProvider` correctly when building Pydantic AI\n agents, and apply an explicit 300s read timeout on the Anthropic streaming\n client (#178).\n- **API:** use axum 0.8 path syntax for `/runs/{id}`.\n\n## [v2026.6.20] — Connections index polish, Skills detail, sidebar dismiss — shipped 2026-06-17\n\n### Changed\n- **Connections index is now searchable, filterable, and sortable.** The list\n reads like the agents/tools tables — a search box, a type filter, and\n sortable column headers (default A→Z by name) instead of a flat list.\n- **Connection detail/edit cleanup.** Every attribute moved into the detail\n table (the header is just the logo + name); all actions (Refresh / Reconnect /\n Edit / Disconnect) sit top-right as buttons styled like the agent view. Edit\n shows only when the connection is actually editable (secret, Composio, or DCR\n native MCP), and renaming is a direct field on the edit page rather than an\n expand-to-rename toggle.\n- **New connection is a two-step picker** — choose a provider / Composio /\n secret, then fill in just that option's form.\n- **Skills: clickable detail view.** Each installed skill links to a detail page\n showing its install source (linked), repo path, file count, and the full\n SKILL.md rendered as markdown, with Remove top-right.\n- **Sidebar \"Action needed\" prompts are dismissible.** A small Dismiss link next\n to Connect hides a connection prompt you don't intend to act on (per-user,\n persisted locally).\n\n### Fixed\n- **Self-key (Tembo) connections no longer flood the audit log.** The implicit\n Tembo Agent Studio connection is re-minted automatically; it no longer writes\n a \"Connection authorized\" event each time. Real OAuth authorizations are still\n audited.\n- **Create-agent prompt hides defunct/renamed native providers** so the Tembo\n Coding Agent isn't offered connections that no longer exist.\n- **CI lockfile.** Repaired a corrupted `web/pnpm-lock.yaml` (duplicate mapping\n keys) that broke `pnpm install --frozen-lockfile`.\n\n### Dependencies\n- Sweep of routine bumps: Next 16.2.9, axum 0.8.9, thiserror 2.0, shadcn 4.11,\n plus the Astro group, `@tailwindcss/postcss`, `eslint-config-next`, chrono,\n regex, uuid, `@types/node`, and `actions/checkout` v6.\n\n## [v2026.6.19] — Connections & Slack apps reworked into list / view / edit — shipped 2026-06-16\n\n### Changed\n- **Connections reworked into an agents-style list.** The tabbed Connections\n shell (Native MCP / Composio / Secrets + an admin sub-page) is now one list of\n every connection you have — native-MCP and Composio OAuth plus workspace\n secrets — each row tagged by type, with a **\"+ New connection\"** button and,\n for admins, **\"Manage providers\"** (provider enable/disable + bring-your-own\n OAuth apps moved to `/connections/providers`).\n - **New connection** is a two-step picker: choose an option (a provider,\n a Composio toolkit, or a secret), then fill in just that option's form.\n - Each connection gets a **detail view** (status, tools, token expiry, with\n Refresh / Reconnect / Disconnect) and an **edit** view (rename, or rotate a\n secret). OAuth flows land you on the new connection's detail page; old\n `/connections/{native-mcp,composio,secrets}` URLs redirect to the new shape.\n- **Slack apps moved to the Build menu, reworked into list / detail / edit.**\n Slack apps left Settings for **Build → Slack apps**: a list of apps (rows),\n a dedicated **New Slack app** view, a detail view with the setup checklist /\n request URLs / manifest / install, and an edit view for credentials. The\n install flow returns to the app's detail page.\n- **Tools: admins see the whole workspace's catalog.** A workspace admin now\n sees tools from every member's active connections on the Tools tab, not just\n their own — so they can see what agents across the workspace can reach.\n (API/MCP/agent surfaces stay per-user.)\n\n## [v2026.6.18] — Audit timeline detail + sign-in redirect for deep links — shipped 2026-06-16\n\n### Fixed\n- **Signed-out deep links now go to sign-in, not a 404.** A signed-out visitor\n following a deep link (e.g. `//audit`) hit a page that gates with\n `notFound()`, so they saw a 404 — which reads as a broken link, not \"please\n sign in\". An auth gate in the proxy (middleware) now redirects them to the\n sign-in landing with the intended path in `?next=`, and they return there once\n signed in. `/mcp` and `/for-agents` stay open (they authenticate with a bearer\n token, not a session).\n\n### Changed\n- **Audit timeline shows real detail for every event.** A full pass over the\n event log:\n - **Connections** show the provider (e.g. *Attio*, *Tembo Agent Studio*) and a\n stack tag (Native MCP / Composio), instead of a bare \"· default\" — native-MCP\n events store the provider slug, which the timeline now resolves to a display\n name.\n - **Every event kind has a human label and an inline summary** where it carries\n useful data (API keys, webhooks, native-MCP OAuth apps, provider toggles,\n secret connections, Slack apps/installs/messages, sign-ins with IP + browser,\n agent version promotions). Previously ~20 kinds rendered as raw strings like\n `api_key.created` with no detail.\n - **A per-row \"Details\" expander** reveals the full event payload for anything\n the summary doesn't surface.\n - **Member events record who invited.** Accepting an invite now records the\n original inviter (`invited by …`), which was previously lost once the invite\n was accepted.\n\n### Dependencies\n- **esbuild 0.28.1, vite 8.0.16, js-yaml 4.2.0, @babel/core 7.29.7.** Clears six\n Dependabot advisories across the two earlier rounds. All are dev/test/build\n tooling (never in the deployed runtime), and the vectors (Deno install path,\n Windows dev server, untrusted-YAML parsing the app doesn't do) don't apply to\n this stack — bumped to keep the security tab clean.\n\n## [v2026.6.17] — Audit coverage for the API/MCP surface, sign-ins, and membership — shipped 2026-06-16\n\n### Added\n- **Audit coverage for the public API & MCP surface.** Mutations made through\n the REST API (`/api/v1`) and MCP server (`/mcp`) — which shipped unaudited in\n v2026.6.16 — now write to the audit timeline, stamped with `via` (`api` or\n `mcp`) and the acting API key so a programmatic change is distinguishable from\n an in-app one and traceable to a key. Covers automation create/update/delete,\n Slack-app create/update/delete, and `send_slack_message` (destination + length\n only — never the message body). Runs and agent-change requests aren't\n double-logged — they already project into the timeline from their own tables.\n The in-app Slack-app management actions, which were also never audited, now\n record the same events.\n- **Sign-in audit events.** A successful login now writes an `auth.login` event\n (with IP address and user agent) to the timeline of each workspace the user\n belongs to, via a better-auth session hook.\n- **Membership & setup audit events.** New events for inviting a member\n (`member.invited`), revoking an invite (`member.invite_revoked`), a member\n joining (`member.added` — on both admin-add and invite-accept), connecting a\n repo (`repo.connected`, which stores a GitHub PAT), creating a workspace\n (`workspace.created`), and syncing agent guidance (`guidance.synced`).\n\n### Dependencies\n- **esbuild → 0.28.1.** Clears two Dependabot advisories\n ([GHSA-gv7w-rqvm-qjhr](https://github.com/advisories/GHSA-gv7w-rqvm-qjhr),\n [GHSA-g7r4-m6w7-qqqr](https://github.com/advisories/GHSA-g7r4-m6w7-qqqr)).\n esbuild is dev/test-only here (transitive via vitest/tsx/vite in `web` and the\n Astro toolchain in `docs`, never in the deployed runtime), and neither\n vector — the Deno install path and the Windows dev server — applies to this\n stack, but bumped to keep the security tab clean. `docs` needed a\n `pnpm.overrides` pin since `astro`/`vite 7` held esbuild at 0.27.x.\n\n## [v2026.6.16] — Public API & MCP server, sub-agent orchestration, prompt caching — shipped 2026-06-15\n\n### Added\n- **Public REST API + MCP server.** Drive a workspace programmatically — from\n Claude Code or any HTTP/MCP client. A new **personal API key** (Settings →\n API keys) authenticates both surfaces as you (your role, your per-user\n connections), is shown once, and can be disabled or revoked anytime.\n - **REST API** under `/api/v1`: list/read agents, validate a spec, list/read\n and trigger runs, browse the tool catalog and connection status, manage\n automations, manage Slack bots (create/update/delete, admin only), and hand\n authoring to the Tembo Coding Agent (`POST /api/v1/agent-changes`). See\n [REST API](./docs/src/content/docs/api.md).\n - **MCP server** at `/mcp` (Streamable HTTP): the same capabilities as MCP\n tools (`list_agents`, `get_agent`, `validate_agent_spec`, `list_runs`,\n `get_run`, `list_tools`, `list_connections`, `list_automations`,\n `list_slack_apps`, `trigger_run`, `create_automation`,\n `request_agent_change`, plus admin-only `create_slack_app` /\n `update_slack_app` / `delete_slack_app`). Connect with\n `claude mcp add --transport http tas https:///mcp --header \"Authorization: Bearer tas_…\"`.\n See [MCP server](./docs/src/content/docs/mcp.md).\n- **Admin Slack-app management over the API & MCP.** The slack-apps surface\n (previously read-only) now supports create/update/delete, gated at\n `workspace_admin` on both REST (`POST /api/v1/slack-apps`,\n `PATCH`/`DELETE /api/v1/slack-apps/{id}`) and MCP (`create_slack_app`,\n `update_slack_app`, `delete_slack_app`) — matching Settings → Slack apps.\n Creation writes metadata only (the app comes up `configuring` and isn't live\n until an admin completes the one-time browser OAuth install), so no secrets\n are needed to create one over the API.\n- **`send_slack_message` — real Slack DMs and channel posts.** Agents could only\n reach Slack via Composio, whose \"DM\" posts to the bot's own connected account\n (the human never sees it). A new `send_slack_message` MCP tool (operator-gated)\n + `POST /api/v1/slack-messages` use a workspace Slack app's bot token to DM a\n real person by `toEmail` (resolved to a real DM + notification) or post to a\n `channel`. So an agent on the `tembo-agent-studio` MCP can actually notify\n someone instead of self-DMing through Composio.\n- **Sub-agent orchestration with rolled-up cost.** When an agent calls the\n `tembo-agent-studio` MCP `trigger_run` from inside its own run (an orchestrator\n fanning work out to per-source sub-agents), the spawned run is now linked to its\n parent (`run.parent_run_id`). The parent's run page gets a **Sub-runs** section\n listing each child with its tokens + cost, a **Combined** total, a **Prompt\n cache** read/write breakdown, and a **Sub-agents use** row of the MCP logos the\n children actually invoked.\n- **Agents list: MCPs column + filter.** The agents inventory shows each agent's\n declared connection logos; for an orchestrator it also shows (dimmed) the MCPs\n its sub-agents bring in, derived from the `parent_run_id` graph. A **Filter by\n MCP** dropdown matches an agent on its own or its sub-agents' MCPs.\n- **Native-MCP tool reference for the Tembo Coding Agent (`/for-agents`).** When\n TAS asks CAP to author or edit an agent, the prompt now lists native-MCP\n connection slots (provider → authorized names) alongside Composio slots, and\n links each instance's own cached tool reference at `GET /for-agents/.md`\n so CAP can learn a native MCP's exact tool slugs. Auth is a signed, expiring,\n `(workspace, user)`-scoped bearer token that unlocks only the tool catalog —\n stateless, no DB key. Connection context is now shared across all three authoring\n call sites (new-agent form, API `request_agent_change`, in-app chat edit).\n- **Orchestration is the preferred multi-source pattern.** The Pydantic AgentSpec\n guide TAS syncs into every connected repo now steers CAP toward a thin\n orchestrator + focused sub-agents (driven through the `tembo-agent-studio` Native\n MCP: `list_connections` / `trigger_run` / `get_run`) instead of one agent holding\n every source's tools in one growing context — and to reuse an existing\n single-purpose sub-agent rather than duplicating it. The guidance version hash\n auto-bumps, so repos re-bootstrap the refreshed guide on their next request.\n- **Native MCP: Tembo Agent Studio (self-key) and Dialed.** Added a\n `tembo-agent-studio` self-key native-MCP provider (so an agent can drive its own\n TAS instance) and [Dialed](https://dialed.day) to the native-MCP catalog. Agents\n declare them with `connections: [{ type: …, source: native-mcp }]`.\n- **Anthropic prompt caching + cache-aware cost.** An agentic run re-sends the\n whole prompt every step, so the large static prefix (system instructions + tool\n schemas) was re-billed at full input rate on each of 10+ steps. The runner now\n caches the system prompt + tool definitions and rolls a breakpoint over the\n growing history (Anthropic models; a spec can override), billing the repeated\n prefix at the cache-read rate (~0.1×) after a one-time write surcharge (~1.25×) —\n roughly a 3–5× cost cut on tool-heavy runs. Cost accounting is now cache-aware,\n and the run-steps footer shows a `prompt cache: N read · M write` line when the\n cache engaged.\n- **Provider logos on native-MCP surfaces.** A shared `mcpLogoUrl(slug)` helper\n serves local art for providers Composio's logo CDN doesn't carry (Pylon, Dialed,\n Tembo Agent Studio) and the CDN for everything else. Logos now render on the run\n page, the agents-list MCPs column, the agent **Uses** row, and all three\n native-MCP card states on the Connections page (each keeping its generic-glyph\n fallback).\n\n### Changed\n- **Native-MCP slots fall back to your sole connection.** A spec that pins a\n provider by a slot name the user didn't use verbatim (e.g. `name: default` vs a\n connection named `tembo`) was rejected as not-connected. Now, when the named slot\n is absent but the user has exactly one active connection for that provider, TAS\n uses it — at both run time and in the pre-run check. Ambiguous (2+ slots, none\n matching) still requires naming one.\n- **Tool catalog hides orphaned tools.** `listToolsForUser` now surfaces a cached\n tool only when a matching active connection still exists, so tools from renamed,\n disconnected, or stale connections no longer linger (e.g. the duplicate listings\n after the `tembo` → `tembo-agent-studio` slug rename). Applies everywhere the\n catalog feeds: Tools tab, Connections, `/api/v1/tools`, MCP `list_tools`, and\n `/for-agents`.\n- **Native-MCP authorizations request `offline_access`.** Providers that only\n issue a refresh token when the OIDC `offline_access` scope is requested (e.g.\n Dialed) were going dark when their short-lived access token expired. TAS now\n appends `offline_access` at authorize time when the auth server supports the\n refresh-token grant (DCR providers only). Existing such connections must be\n reconnected once to obtain a refresh token.\n\n### Fixed\n- **Native-MCP token refresh for Dialed/Fathom.** The Rust refresh path validates\n a connection's origin against its own hardcoded allowlist, which lagged the web\n catalog — so every Dialed refresh aborted, the expired token was used, and the\n run 401'd. Added Dialed + Fathom to the allowlist and a vitest drift guard that\n fails CI if a future catalog provider isn't mirrored into the Rust allowlist.\n- **Defunct native-MCP connections can be cleaned up.** A connection to a provider\n that left the catalog (e.g. the old `tembo` self-key connection after the rename)\n lingered as an orphaned row that couldn't be disconnected and kept its minted\n `tas_` key alive. The Connections → Native MCP page now shows a \"removed provider\"\n banner with a one-click Remove that deletes the rows, revokes the self-key, and\n drops the cached tools.\n- **Sidebar stopped nagging \"Connect\" under the single-connection fallback.** The\n sidebar's \"Action needed\" list reimplemented the missing-connection check with a\n strict slot-name match and lacked the native single-connection fallback, so it\n flagged a connected agent as needing attention. Both the sidebar and the run-\n blocking pre-flight now route through shared helpers so they can't drift again.\n- **YOLO creates show a pending card immediately.** A YOLO (direct-commit) create\n is optimistically marked committed the moment CAP accepts it, but the agents page\n re-filtered pending creates to only submitted/PR-opened ones — so a YOLO create\n showed nothing until Tembo finished building it. The page filter now keeps\n direct+committed creates too, matching the query.\n\n### Migrations\n- `0049` (per-user, workspace-bound API keys) and `0050` (`run.parent_run_id` for\n sub-run linking) apply on the next Rust api restart.\n\n## [v2026.6.15] — Fathom MCP, free-text agent names — shipped 2026-06-09\n\n### Added\n- **Run input on the run view.** A run started with an optional message now shows\n that text as an **Input** field (under Trigger) on the run detail page.\n- **Fathom Native MCP.** Added [Fathom](https://fathom.video) (meeting\n notes/transcripts) as a native MCP provider — connect it from Connections with\n TAS-managed OAuth (Fathom supports dynamic client registration + PKCE, so\n there's no per-customer OAuth-app setup). Agents reach it with\n `connections: [{ type: fathom, source: native-mcp }]`.\n- **Free-text agent names.** Name an agent in normal text (e.g. \"Inbox Triage\")\n — the create form slugifies it for the filename and saves the text as a new\n optional `title:` field on the spec. The agents list, agent page, and chat\n header show the `title` (falling back to the slug); the slug `name` stays the\n stable identifier for URLs, runs, and automations, so nothing else changes.\n\n### Fixed\n- **Run-now dropped the optional message.** The \"Run now\" dialog's submit button\n was a Radix `AlertDialogAction`, which dismissed (unmounted) the dialog the\n instant it was clicked — racing the form submission and sending the agent an\n empty `user_message` (so it behaved as if no input was given). Now a plain\n submit button: success redirects, errors keep the dialog open with the input.\n- **Historical run-cost backfill.** Recomputed the stored `cost_usd` on existing\n runs against the corrected model rates (Opus $5/$25; gpt-5.x priced per\n variant), so the Runs list and dashboard totals match the run-detail estimates\n for pre-fix runs. Only rows with token counts + a known model family are\n touched; unknown models and already-correct families are left as-is.\n *(migration 0048)*\n\n## [v2026.6.14] — Agent Skills, YOLO mode, Claude Fable 5 — shipped 2026-06-09\n\n### Added\n- **Agent Skills.** A workspace **Skills** area to install reusable Agent Skills\n (Anthropic's `SKILL.md` folders) into your repo under `skills/`, from three\n sources: the [skills.sh](https://www.skills.sh/) directory (by slug / GitHub\n URL), a custom `.zip` upload, or **imported from the Claude Skills API** (the\n org's custom skills + Anthropic's pre-built ones, via the version-content\n export). An agent opts in with a `skills:` field; at run time the named skill\n folders are mounted via pydantic-ai-skills so the model can load their\n instructions and run their scripts — **locally, with any model** (no Anthropic\n code-execution sandbox). Install/remove is workspace-admin and audited.\n- **YOLO (direct-commit) delivery mode.** A per-workspace setting\n (**Settings → Tembo Coding Agent → Improvements delivery**) chooses how the\n coding agent's changes land: **Always PR** (default — a reviewable pull\n request) or **YOLO**, which commits straight to the default branch with no PR.\n The mode is read per request to shape the Tembo prompt, so toggling takes\n effect on the next submission with no repo re-sync. YOLO improvements show a\n terminal **Committed** status and link the landed commit; a best-effort scan\n finds the marker commit on the default branch to attach it. Switching mode is\n workspace-admin-only and audited. *(migration 0047 — `workspace.commit_mode`\n + `improvement.delivery` / `commit_sha` / `commit_url`)*\n - YOLO requires the default branch to accept direct pushes from the coding\n agent; if it's protected behind required pull requests, keep Always PR.\n- **Claude Fable 5 support.** Agents can use `anthropic:claude-fable-5` —\n Anthropic's most capable widely-released model (Mythos-class, 1M context),\n GA on the Claude API as of 2026-06-09. Priced in the run-cost estimates at\n $10/$50 per MTok (web + API tables), and added to the authoring guidance as\n the top-capability step-up above Opus 4.8.\n\n### Fixed\n- **Opus run-cost estimates.** Corrected the `claude-opus` rate from the stale\n $15/$75 to the current $5/$25 per MTok (current Opus 4.5–4.8), so cost\n estimates and the stored `cost_usd` are accurate. (The $15/$75 rate only ever\n applied to the deprecated Opus 4.1/4.0.)\n- **OpenAI gpt-5.x run-cost estimates.** The single `gpt-5` rate ($1.25/$10) was\n mis-pricing the whole gpt-5.x family. Added per-model rates for the current\n flagships and intermediate releases — gpt-5.5 ($5/$30), gpt-5.4 ($2.50/$15,\n + mini/nano), gpt-5.2 ($0.875/$7), gpt-5.1 ($0.625/$5) — ahead of the bare\n `gpt-5` catch-all. gpt-4o / gpt-4.1 / o3 were already correct. Authoring\n guidance now references `openai:gpt-5.5` instead of the older gpt-5.2.\n\n## [v2026.6.13] — In-app docs, workspace rename, Automations area — shipped 2026-06-09\n\n### Added\n- **In-app documentation.** The product manual now ships inside the app, pinned\n to the exact version you're running — a **Docs** link in the sidebar opens a\n full viewer with search, a sticky collapsible nav whose open/closed state\n persists across sessions, and a GitHub-stars link in the footer. Content is\n organized by audience — **For Operators** (The Basics / Advanced), **For\n Admins** (workspace admin + self-hosting), and **For Instance Admins** — and\n every page, including the live **Changelog** and **Roadmap**, is bundled at\n build time so it always matches the deployed release.\n- **Rename a workspace.** A new **Settings → General** section (workspace-admin\n only, now the default Settings tab) renames a workspace. GitHub-org style: the\n URL slug follows the name, and the previous slug is kept alive as a redirect —\n preserving deep links (`/old/agents/x` → `/new/agents/x`) — so existing links\n and bookmarks never break. Renames are recorded in the audit log. *(migration\n 0046 `workspace_slug_alias`)*\n- **Workspace-level Automations area.** A dedicated **Automations** section in the\n sidebar with its own nav — **Schedules**, **Triggers**, and **Webhooks** — so\n recurring runs and event wiring have a home across the whole workspace, not\n just per-agent. On the agent page, Schedules moved to the top of the renamed\n **Automation** tab.\n- **Role badge in the shell.** Your workspace role (Workspace Admin / Operator /\n Viewer) now shows under your name in the bottom-left user menu.\n- **Agents table filters.** Filter the agents inventory by label and by model.\n\n### Changed\n- **Roadmap rewritten** as a simple, unphased list of ideas — each described in a\n couple of sentences and linked to a GitHub Discussion holding a draft **TASIP**\n (Tembo Agent Studio Improvement Proposal) where you can weigh in.\n- **Docs stay in sync by policy.** `AGENTS.md` now instructs coding agents to\n update the docs alongside feature changes, backed by a non-blocking CI reminder\n when app code changes without a matching docs change.\n\n### Fixed\n- **Reliable merged-PR detection for improvements.** Improvements with a known PR\n number are now confirmed via a direct PR fetch instead of the search API, so a\n merged improvement no longer lingers as \"open\".\n\n## [v2026.6.12] — Live run timeline, output discipline, Native MCP admin — shipped 2026-06-08\n\n### Added\n- **Run view rebuilt as a live step timeline.** The run-detail page now shows\n one view — built live and identical when finished — of what the agent did,\n step by step: the model's narration (revealed word-by-word while running), the\n tools it called (provider logo + ok/failed/running badge inline), and a\n per-step **In / Out token + cost** readout, with a totals footer (In, Out, and\n combined total). A \"Copy\" button lifts the whole transcript (narration +\n answer + tool calls) as plain text. The final answer is the last step — no\n separate Output box.\n - The wrapper streams text deltas + tool-call/result events as they happen; the\n runner persists `run_step` / `run_tool_call` rows live so the table builds in\n place, reconciled authoritatively at run end.\n - Per-step token usage + per-tool-call attribution. *(migrations 0043\n `run_step`, 0044 `run.streamed_output`, 0045 `run_step.summary`)*\n- **Output discipline for every agent.** A global instruction makes agents work\n silently — no step-narrating or raw tool-output dumps in the reply — while\n allowing one short \"what I'm doing\" line per tool step (which feeds the\n timeline narration). Stops agents from burning the output-token budget.\n- **Real parallel-tool-call limiter.** Agents now default to\n `model_settings.parallel_tool_calls = False` — an API-level cap so the model\n issues one tool call at a time instead of fanning out parallel bursts that get\n providers (e.g. Attio) rate-limited. Opt back in per-agent via the spec. Paired\n with tool-use guidance to back off on `retry after` errors.\n- **Native MCP admin screen.** A workspace-admin \"Manage providers\" screen\n (Connections → Native MCP) to enable/disable which providers members see and\n register **multiple named OAuth-app instances** per confidential provider, so a\n second connection can use a second app. *(migration 0042\n `workspace_native_mcp_provider` + instance columns on\n `workspace_native_oauth_client`)*\n\n### Changed\n- **Agents table:** Name is the first column with alphabetical default sort;\n Labels get their own column; the Framework column is gone; the Model column\n strips the provider prefix (`anthropic:claude-sonnet-4-6` → `sonnet-4-6`).\n- **Per-agent Runs tab** reuses the workspace Runs table (same columns minus\n Agent + Input), keeping status/trigger/search filters.\n- **Sidebar \"Action needed\"** collapses duplicate missing-connection alerts into\n one card (\"HubSpot for 3 agents\") instead of one per agent.\n- **Dashboard:** dropped the \"Workspace-wide activity\" subhead; Recent runs now\n show who triggered each run.\n\n### Migrations\n- `0042_native_mcp_admin` — provider enable flags + OAuth-app instances.\n- `0043_run_step` — per model-step token usage + `run_tool_call.step_ordinal`.\n- `0044_run_streamed_output` — live partial output column.\n- `0045_run_step_summary` — per-step narration text.\n\n## [v2026.6.11] — HubSpot via Native MCP (bring-your-own OAuth app) — shipped 2026-06-08\n\n### Added\n- **HubSpot as a Native MCP provider** (`https://mcp.hubspot.com`). HubSpot\n doesn't support auto-registration (DCR) and uses a confidential OAuth client,\n so this adds a **\"bring-your-own OAuth app\"** mode to Native MCP — generic for\n any future non-DCR provider:\n - `McpProvider.authMode` (`dcr` | `manual`); manual providers run a\n confidential PKCE flow with an admin-stored client_id/secret instead of\n self-registering a public client.\n - An admin **Configure OAuth app** card on **Connections → Native MCP** shows\n the redirect URI to register and stores the client_id/secret (encrypted);\n the per-user **Connect** button is gated until it's configured.\n - Token refresh presents the confidential client_secret for these\n connections. *(migration 0041 `workspace_native_oauth_client`)*\n\n To use it: create a HubSpot MCP auth app with redirect URI\n `/api/connections/native/hubspot/callback`, paste its client_id/secret\n under Connections → Native MCP, then Connect and reference\n `{ type: hubspot, source: native-mcp }` in an agent.\n\n### Changed\n- **Automations** collapses by default on the agent Automation tab (matching\n Triggers + External webhooks), with a count in the title.\n\n### Migrations\n- `0041_workspace_native_oauth_client` (per-workspace BYO OAuth client for manual\n Native MCP providers). Applied on api boot.\n\n## [v2026.6.10] — Agent view redesign + run-time connection guard — shipped 2026-06-08\n\nThe agent page was a long vertical stack; it's now a focused, Settings-style\nview with a left side-nav. Plus a guard that stops a run before it starts when\nthe connections aren't set up. Web-only — no new migrations.\n\n### Added\n- **Agent view side-nav** — the agent page is reorganized into a shared header\n (name, version, owner, connections, primary actions) + a left tab rail, with\n one real route per tab: **Overview** (30-day dashboard + recent runs),\n **Runs**, **Automation** (triggers + webhooks + schedules), **Versions**,\n **Definition** (spec + tools module), **Activity** (audit timeline), and\n **Settings**. Each tab fetches only its own data.\n- **Connection icons on the agent view** — a row of the external services the\n agent uses, each with its **provider name + logo** (logos borrowed from\n Composio's library; a generic icon when a slug has none).\n\n### Changed\n- **Decluttered the agent header** — Delete moved to **Settings → Danger**;\n **Promote to Stable** moved to the **Versions** tab (the header keeps the\n read-only \"Stable vN\" badge); the ownership picker moved to **Settings** (the\n header shows a read-only owner). The header's action row is just\n **View source · Chat to edit · Run now**.\n- **Triggers + External webhooks collapse by default** on the agent view, with a\n count in the title so configured items stay visible.\n\n### Fixed\n- **Block a run when the acting user's connections aren't set up** — a clear\n pre-flight message (\"You haven't connected: HubSpot. Authorize under\n Connections, then run again.\") instead of a pydantic-ai traceback mid-run.\n Applies to Run-now and Chat-to-edit.\n- **Lint/CI** — pin `eslint` to 9 (eslint 10 removed an API `eslint-plugin-react`\n still uses, crashing the lint step), and fix the placeholder Dependabot config\n (real per-ecosystem groups; Astro + Starlight always bump together).\n\n### Dependencies\n- A wave of Dependabot updates: Next 16.2.7, React 19.2.x, Astro 6.4.4,\n TypeScript 6, and many GitHub Actions (`checkout`, `setup-node`, the docker/*\n actions, codeql, pages) — all verified green.\n\n## [v2026.6.9] — Agent lifecycle, tool observability, and the ETL-agent stack — shipped 2026-06-08\n\nA big release. Agents gain a real **version lifecycle** (draft → stable) and\n**tool-call observability**, and a new **ETL-agent stack** lands: agents can run\ndeterministic **Python tools**, authenticate them through a new **Secrets**\nsubstrate, and be **triggered by external webhooks** (Clay first). The full\n**user manual** is now published, and the `guides/` directory moved into it.\n\n### Added\n- **Agent versioning & lifecycle** — agents now have a **draft** (the live repo\n file) and a promotable **stable** snapshot frozen in Postgres. Promotion\n records owner + version; runs default to **stable** for predictability (chat\n iterates on draft). The agent page shows version history, the draft↔stable\n diff, and a change summary. *(migration 0037)*\n- **Sidecar Python tools** — a Pydantic agent can declare `tools_module: foo.py`,\n a sibling file of deterministic functions the model calls as tools (transforms,\n scoring, ETL) at **no token cost**. Schemas derive from each function's\n signature + docstring; calls are captured like MCP tools. Extra deps go in\n `api/scripts/requirements-tools.txt`.\n- **Secrets — the 3rd connection substrate** — free-form, per-workspace API keys\n (e.g. Clay) set under **Connections → Secrets** (admin-managed, AES-256-GCM).\n Sidecar tools read a value via `tas_tools.secret(\"\")`; injected only\n into runs that have a tools module. *(migration 0039)*\n- **External webhook triggers** — a per-agent inbound endpoint\n (`/api/hooks/webhook/`) fires a run from any outside system. Built for\n Clay's model: `POST` JSON + an `Authorization: Bearer ` header\n (constant-time verified, shown once, rotatable); fire-and-forget 202. The\n request body reaches the agent as a `{trigger_type, webhook, payload}`\n envelope. *(migration 0040)*\n- **Tool-usage tracking** — every tool an agent calls is captured per run\n (success + failure), rolled up per agent over 30 days, and surfaced in a\n workspace-wide, filterable **Tool uses** view. *(migration 0038)*\n- **Pylon** as a Native MCP provider.\n- **Two-level collapsible sidebar** navigation (Build / Activity / Integrations /\n Workspace).\n- **Published user manual** — an Astro Starlight site at\n , deployed from `docs/` on every change.\n\n### Changed\n- **Prefer Native MCP over Composio** in the agent-authoring guidance, with a\n dynamic provider list; default model guidance moved to `claude-opus-4-8`, and\n the `labels:` extension field is documented.\n- **`guides/` merged into the docs site** and deleted; the README and deploy\n guides now point at the published manual.\n\n### Fixed\n- **Native MCP token refresh** for short-lived tokens (Pylon ~5-min tokens) via a\n per-provider refresh allowlist.\n- **Composio**: surface connect errors instead of swallowing them; support\n bring-your-own-auth toolkits; flag unknown toolkit slugs; fix a Pylon→Linear\n OAuth misroute and a \"no active connection\" false negative.\n- **Agent versioning**: fix a promote crash (`FOR UPDATE` with an aggregate) and\n owner-picker name disambiguation.\n- **\"Improve the Agent\"** now surfaces a thrown/stale server action (\"refresh —\n a new version shipped\") instead of failing silently.\n- **Docs build**: upgrade Starlight to 0.39 for Astro 6 compatibility, and\n replace the placeholder Dependabot config with real per-ecosystem groups\n (Astro + Starlight always bump together).\n\n### Migrations\n- `0037_agent_version`, `0038_run_tool_call`, `0039_workspace_secret_connection`,\n `0040_workspace_webhook`. The api applies them on boot.\n\n## [v2026.6.8] — Slack apps: launch agents from Slack — shipped 2026-06-04\n\nTAS can now host per-team Slack bots that launch a **label-scoped subset** of\nyour agents — separating cheap routing from right-sized execution, so dozens of\nagents are reachable from Slack without dozens of channels or one expensive\nmega-agent.\n\n### Added\n- **TAS-managed Slack apps** (Settings → Slack apps, admin-only) — register one\n bot per team (e.g. a sales bot and a support bot), each scoped to a subset of\n agents by label. Coached setup: copy a prefilled Slack manifest, paste\n credentials, then **Add to Slack** (OAuth) to install. Signing secret, client\n secret, and bot token are AES-256-GCM encrypted; multi-app from day one.\n- **Launch agents from Slack** — slash command `/tas `,\n `@mentions`, and DMs. The run acts as the Slack user (matched by email),\n falling back to the app's default owner, and the result posts back in-thread.\n- **Agent labels** — add `labels: [sales]` to an agent spec to group it in the\n inventory and scope which Slack app may launch it. Documented as a TAS\n extension field in [`AGENT_FORMAT.md`](./context/shipped/0.1/AGENT_FORMAT.md).\n- **Natural-language routing** — a Slack message that doesn't name an agent is\n routed by a cheap Haiku 4.5 classifier to the best-fit scoped agent (or replies\n with the menu when nothing fits).\n- **Agent picker modal + App Home directory** — `/tas` with no agent opens a\n picker; the bot's Home tab lists every agent it can launch.\n- **\"Run agent on this message\" shortcut** — launch an agent with any Slack\n message as its input, prefilled into the picker.\n- **Runs \"Source\" column** — the runs list now shows how each run was instigated\n (Manual / Scheduled / Event / Slack), who it acted as, and — for Slack — a deep\n link back to the originating conversation.\n- **Dashboard \"Slack (30d)\" column** — per-member count of Slack-launched runs,\n with a per-bot breakdown on hover.\n\n### Changed\n- Slack replies render the agent's Markdown as Slack **mrkdwn** (bold, headings,\n links, bullets, tables) and drop the leading `user>` transcript echo.\n- Dashboard **Team** rows append the email when two members share a first name.\n\n### Hardening\n- Per-Slack-user rate limit, replay dedupe on Slack retries, and an audit event\n (`slack.dispatch`) per Slack-launched run.\n\n### Fixed\n- Slack Web API calls are now form-encoded — fixing the read methods that\n silently ignore a JSON body, so the acting-user email→member mapping and the\n message permalinks (the \"View in Slack\" links) work.\n\n## [v2026.6.7] — Team visibility + admin management — shipped 2026-06-04\n\nA batch focused on workspace admins seeing and managing what members own.\n\n### Added\n- **Team section on the dashboard** — a per-member table (Connections /\n Automations / 30-day runs), sorted by run activity. Hover a count for the\n underlying list (which toolkits are connected, which agents have\n automations) via a styled, fast tooltip.\n- **Member detail view** — admins click a member (from Settings → Members or\n the Team table) to see their tool connections, the automations that \"Run as\"\n them, and their recent runs. Useful before offboarding (see #64).\n- **Admins can view + rename any member's connections** — a \"Viewing\" dropdown\n on the Connections page (defaults to self). When viewing another member you\n can Rename and Refresh; Connect/Reconnect/Disconnect are hidden since OAuth\n must be performed by that member.\n- **Admin \"Run as\" in the manual Run-now dialog** — pick which member to run as;\n the run uses that member's connections (same model as an automation owner).\n- **\"Run as\" owner column** on the automations list.\n\n### Changed\n- Member rows: **Remove** is red with a confirm step, and the whole row links to\n the member detail view.\n- The Composio connection-rename action is now gated to owner-or-admin (parity\n with the native-MCP rename).\n\n## [v2026.6.6] — Dismiss pending agents + settings polish — shipped 2026-06-04\n\n### Added\n- **Dismiss pending agents** from the workspace home. In-flight chat-to-PR\n creates can now be removed from the inventory via an inline confirm\n (operator+); it stops tracking the create here and leaves the GitHub PR\n alone (the PR / Tembo-session links still reach it).\n\n### Fixed\n- **Composio webhook secret field** no longer implies a `whsec_` prefix — those\n secrets are prefix-less hex, so the masked preview/placeholder were\n misleading (same class of fix as the Tembo API key field in v2026.6.5).\n- **Sidebar \"Action needed\" CTA** (the \"add an LLM key\" prompt) now updates\n without a manual browser refresh when a provider key is added or removed — it\n lives in the workspace layout, which now revalidates at layout level.\n\n## [v2026.6.5] — Tembo authoring fix + favicon fixes — shipped 2026-06-03\n\n### Fixed\n- **Tembo Coding Agent authoring (the \"Invalid token\" 401).** Requests now hit\n `POST /public-api/task/create`, where the workspace's Tembo API key\n authenticates as `Authorization: Bearer`. We were calling the bare\n `/task/create` path, which a different internal auth gate rejected with\n \"Unauthorized - Invalid token\" — so new-agent / chat-to-edit / Improve failed\n even with a valid key. **This is the fix that unblocks authoring.**\n- **Workspace favicon blank in production.** The favicon route's redirect used\n the container's internal address (`https://0.0.0.0:8080/…`) behind the proxy,\n which the browser can't reach; it now emits a relative `Location`. Also\n cache-busts the default and per-workspace favicon URLs so a stale per-origin\n favicon entry clears (and switching a workspace's favicon actually updates).\n- **Tembo API key field** no longer shows a misleading `tembo_` prefix in the\n masked preview/placeholder — keys are prefix-less.\n\n### Added\n- **Actionable Tembo auth errors.** A rejected/rotated key now surfaces \"Tembo\n rejected the API key — update it under Settings → Tembo Coding Agent\" instead\n of a raw 401, across the new-agent / chat / Improve flows.\n- **Setup guide:** the agents repo must also be authorized in Tembo (Settings →\n Integrations → Source Control) for the coding agent to open PRs.\n\n### Changed\n- Sidebar agents icon matched to Tembo's (#61).\n- Docs: clarified CalVer is year.month + a per-month release counter (not the\n day of the month).\n\n## [v2026.6.4] — Workspace deletion, invite auto-join, LLM-key CTA — shipped 2026-06-03\n\n### Fixed\n- **Invited existing users now join automatically.** Inviting someone who\n already had an account previously left a pending invite with no way to accept\n it — on sign-in they were prompted to create their own workspace instead of\n landing in the one they were invited to. Existing users are now added to the\n workspace at invite time, and any already-pending invite resolves on the\n user's next sign-in. (Recommended upgrade for instances using invitations.)\n\n### Added\n- **Delete a workspace** — Settings → **Danger** tab, with a type-to-confirm\n step, gated to workspace admins. Removes all workspace data (members, runs,\n schedules, connections, secrets, settings, audit, invitations); the GitHub\n repository and its agent files are not touched.\n- **Sidebar CTA when no LLM provider key is set** — a workspace with neither an\n Anthropic nor OpenAI key now shows an \"Action needed\" card linking to\n Settings → LLM Providers, since agents can't run without one.\n\n## [v2026.6.3] — Security hardening, dashboard runs, version surfacing — shipped 2026-06-03\n\nA security-focused release (several authorization/tenant-isolation fixes), plus\ndashboard and CI improvements. **Recommended upgrade for all instances.**\n\n### Fixed (security)\n- **Reject an insecure placeholder `BETTER_AUTH_SECRET` at runtime** — the app\n now refuses to start with the dev placeholder secret, so a misconfigured\n deploy can't run with a guessable session-signing key (#52).\n- **Tenant scoping on the run-detail endpoint** — `get_run` now enforces the\n caller's workspace, preventing cross-workspace run reads (#58).\n- **Authorization check on repo connect** — `connectRepoAction` was missing a\n role check; added it so only authorized members can connect a repo (#55).\n- **Mass-assignment fix** — `owner_user_id` can no longer be set from request\n input (#56).\n- **SSRF + token exfiltration fix** — closed a server-side request forgery /\n token-leak path (#57).\n\n### Added\n- **Settings → Version tab** — shows the running release (release builds link to\n their GitHub release; edge/CD builds link to the commit).\n- **Recent runs on the dashboard** — the latest runs workspace-wide, above\n Improvements, with fully clickable rows linking to the run.\n\n### Changed\n- **CI checks gate + tests on PRs.** A `checks` workflow now runs on every PR:\n web typecheck + vitest + eslint (now blocking after the lint cleanup in #54),\n and api `cargo fmt --check` + clippy + `cargo test`. A separate pipeline\n continuously deploys `main` to Tembo's internal instance behind that gate.\n- **Docs:** Railway guide documents pinning explicit version tags for\n production vs. `:latest` for throwaway instances.\n\n## [v2026.6.2] — Reproducible runtime, setup guide, Microsoft sign-in fix — shipped 2026-06-02\n\nA small maintenance release: lock the last floating runtime dependency so a\nrebuilt image tag is reproducible, ship a start-here setup guide, and fix\nMicrosoft Entra sign-in for self-hosted instances.\n\n### Fixed\n- **Microsoft Entra sign-in.** Entra commonly omits the `email` claim from both\n the id_token and the userinfo endpoint (the address lives in\n `preferred_username`/`upn`), which made better-auth fail sign-in with\n `email_is_missing`. The Microsoft provider now decodes the id_token and\n derives the email from `email ?? preferred_username ?? upn`.\n- **Opaque sign-in errors.** Failed OAuth callbacks redirected back with a bare\n `?error=` and no UI feedback; the sign-in page now renders an actionable\n message (invite-only, missing email, token exchange, …) and surfaces the raw\n code for support.\n\n### Changed\n- **Pinned `composio==0.13.1`** in the api runtime image. It was the one\n unpinned Python dep (pydantic-ai and pyyaml were already pinned); since\n Composio ships frequently, an unpinned bump could break connection-using\n agents on the next rebuild of a given image tag.\n\n### Added\n- **Version on the login screen.** The footer now reads \"powered by Tembo Agent\n Studio ``\" so operators can see at a glance which release an instance\n is running. The version is **baked into the image at build time** (web\n Dockerfile `TAS_VERSION` build-arg), so it always matches the running image —\n no env var to set or keep in sync per instance.\n- **`guides/CUSTOMER_SETUP.md`** — a zero-to-running checklist covering\n everything a new customer must procure and do: infra, auth provider, LLM\n keys, secrets, deploy env, first-run instance-admin bootstrap, per-workspace\n setup, and creating the first agent. Linked from the README as the\n start-here guide.\n\n## [v2026.5.31] — Container image publishing — shipped 2026-05-31\n\nMakes TAS deployable from prebuilt images instead of a source build, and\nhardens the supply chain around them.\n\n### Added\n- **Container images published to GHCR.** A release workflow\n (`.github/workflows/release.yml`) builds and pushes `tas-api` +\n `tas-web` to `ghcr.io/tembo/` on every `v*` tag, tagged\n `` / `.` / `latest`. Images are **cosign**\n keyless-signed and carry SBOM + provenance attestations; **Trivy**\n scans each image (report-only). A `compose.release.yaml` runs the\n stack from those images (`docker compose -f compose.release.yaml pull\n && up -d`), pinned by `TAS_VERSION` and kept in lockstep with each\n release via an auto-opened PR. Customers no longer compile Rust/Node\n on their host.\n- **Onboarding sign-out link.** A \"Signed in as … Not you? Sign out\"\n affordance on both onboarding steps (`/onboarding` and\n `/onboarding/repo`) so someone who authenticated with the wrong\n Google account can recover without an app shell to hang a user menu\n off of.\n- **Dependabot** enabled for GitHub Actions + npm.\n- **Instance-admin role + root `/settings`.** Deployment-level admin via\n the `INSTANCE_ADMIN_EMAILS` allowlist, and a root `/settings` surface\n (instance-admin only) with an editable, DB-backed instance name\n (`instance_settings`, migration 0031; env fallback).\n- **Invite-only instance + workspace invitations.** Account creation is\n rejected unless the email is an instance admin or has a pending invite.\n Workspace admins invite by email (migration 0032) and get a copy-paste\n template; invitees auto-join their workspace(s) on first sign-in.\n Workspace creation is instance-admin-only. `INSTANCE_ADMIN_EMAILS` is\n the required bootstrap env (without it nobody can sign in to a fresh\n instance).\n- **Build fix:** `api/build.rs` (`rerun-if-changed=migrations`) so new\n migrations actually embed in the image — `sqlx::migrate!` is\n compile-time, and a migration-only change otherwise got cached out.\n\n### Changed\n- **api image runs as a non-root user** (uid 1001), matching web. The\n run path writes nothing to disk (spec via stdin, result via stdout),\n so no writable app dir is needed.\n- **api defaults to a dual-stack bind** (`API_BIND_ADDR=[::]:8080`).\n Serves IPv4 + IPv6, so Docker Compose is unchanged while IPv6-only\n private networks (e.g. Railway service-to-service) reach the api with\n no configuration.\n\n### Fixed\n- **Client auth base URL is resolved at runtime** from the browser\n origin instead of the build-time `NEXT_PUBLIC_BETTER_AUTH_URL` (which\n is inlined when the image is built, so a prebuilt GHCR image baked\n `http://localhost:3000` and sign-in failed on any real domain). Fixes\n sign-in for every image-based deploy.\n- **postcss bumped to ≥ 8.5.10** via a pnpm override to clear\n GHSA-qx2v-qp2m-jg93 (a CSS-stringify XSS in the copy Next pins\n transitively). Not reachable in TAS — build-time, dev-authored CSS —\n resolved to clear the alert and de-dupe to one postcss.\n\n## [v2026.5.29] — First CalVer release — shipped 2026-05-29\n\nThe cutover to date-based releases. Everything through Phase 0.4\n(Governance depth) is captured below; this tag marks the first release\ncut from `main` under the new scheme and ships one new capability on top\nof v0.4.\n\n### Added\n- **Native-MCP OAuth token auto-refresh.** The runner now refreshes\n expiring native-MCP access tokens *before* a run reads them, instead\n of letting an expired token reach the agent and 401 mid-run. For any\n active oauth2 native connection (e.g. Attio) whose `token_expires_at`\n is at/near expiry, it spends the stored `refresh_token` (granted via\n `offline_access`) for a fresh token at the provider's discovered token\n endpoint, re-encrypts the credentials, and bumps `token_expires_at`.\n A rejected refresh (dead refresh token) proactively flips the\n connection to `stale` so the UI prompts Reconnect; transient failures\n are logged and the run proceeds on the existing token. Best-effort and\n per-connection. `crypto.rs` gained an `encrypt()` twin to its existing\n `decrypt()`; refresh lives in the runtime (`native_oauth.rs`) so no\n plaintext round-trips through the web container.\n\n### Changed\n- **Roadmap tracking moved to GitHub Issues.** Phase 0.5 / 0.6 user\n stories and the backlog are now issues (label `enhancement`; 0.5 and 0.6\n milestones, backlog = no milestone). The `context/*/USER_STORIES.md`\n docs are redirect pointers to the issues and retain design rationale +\n out-of-scope notes.\n- **Version files adopt CalVer.** `api/Cargo.toml` and\n `web/package.json` move from the long-stale `0.1.0` to `2026.5.29`.\n\n## [v0.4] — Governance depth — shipped May 2026\n\n### Added\n- **Native MCP connections.** Second connection substrate alongside\n Composio: TAS-managed OAuth straight to the provider's official\n MCP server. The user clicks Connect and TAS performs MCP-spec\n discovery + Dynamic Client Registration (RFC 7591) + PKCE under\n the hood — no per-provider OAuth-app setup, no `build.attio.com`\n side quest. `lib/mcp-providers.ts` is a one-line-per-provider\n catalog (today: Attio); everything else (auth URL, token URL,\n scopes, DCR endpoint) is read from `/.well-known/oauth-protected-\n resource`. Agent spec `connections:` entries dispatch by\n `source:` (`composio` default, `native-mcp` opt-in); the Python\n wrapper builds one `MCPToolset` per declared (provider, name)\n slot with the user's bearer token in `Authorization` headers and\n honors `tools:` narrowing on native entries via\n `FilteredToolset`. Rust runner decrypts the `workspace_connection`\n row per acting user and ships the credentials as\n `TAS_NATIVE_MCP_CONNECTIONS` env.\n- **Unified tool catalog + Tools tab.** Normalized\n `workspace_mcp_tool` table (migrations 0029 + 0030) caches every\n tool exposed by any connection, indexed by source + provider +\n connection name. Primed on connect, refreshable from a per-row\n button on the Connections page, cleared on disconnect. New\n workspace-level `//tools` page lists everything in a\n searchable, filterable table with click-to-copy slugs — kills\n the \"is it `RUN_BASIC_REPORT` or `run-basic-report`?\" guessing\n game that the kebab-case-vs-UPPER_SNAKE_CASE split between\n Attio's MCP and Composio's REST wrappers used to force on you.\n- **Lean CAP prompt + canonical agent guidance.** Tembo Coding\n Agent prompts dropped ~16KB by replacing the inline canonical-\n guidance block with a pointer at the on-disk files (Sync agent\n guidance pushes the canonical content to the customer repo on\n demand; a scheduled refresh lives in\n `context/backlog/`). `PYDANTIC_GUIDE` learned both connection\n substrates, the slug-case gotcha, and a Switching-from-Composio-\n to-Native-MCP recipe.\n- **Test foundation (Vitest + Polly.js + Playwright/Cucumber).**\n `pnpm test` runs unit + integration in ~300ms covering the RBAC\n policy + the workspace-authorize funnel (the v0.4-02 deny-test\n exit-bar item — operator is denied workspace_admin actions,\n no-session short-circuits before workspace lookup so existence\n isn't leaked). `pnpm test:bdd` drives a real Chromium through\n Gherkin-style feature files via Cucumber.js — pilots: anon\n redirects to sign-in, signed-in workspace_admin lands on the\n dashboard (seeded via direct Postgres write + HMAC-signed\n session cookie). HTTP fixtures recorded as Polly.js cassettes.\n- **Immutable audit changelog (US-0.4-01).** Append-only\n `audit_event` table records actor / when / source / target /\n payload for the event types that don't already live in another\n table (secret rotations, connection authorize/disconnect/rename,\n automation lifecycle, trigger lifecycle, agent delete/restore,\n repo disconnect). The unified timeline reads explicit writes\n UNION'd with derived projections of `run` + `improvement` (both\n already event-shaped), so v0.3 emitters needed zero\n re-instrumentation. Workspace-wide `//audit` page\n with source / actor / agent / time-window filters (URL-driven,\n deep-linkable). Per-agent Timeline section on the agent detail\n page with click-through to the full history. New `Audit`\n sidenav item.\n- **Audit JSON export (US-0.4-04).** \"Export JSON →\" affordance\n on the audit page (honors current filter set) and the per-agent\n Timeline (scoped to that agent). Envelope carries the filter\n snapshot + truncated flag alongside the rows. Export is itself\n audited (`kind=audit.exported`). Capped at 10,000 rows per\n download — streaming to a SIEM is the v0.5 open question per\n the story carve-out.\n- **RBAC (US-0.4-02).** Three workspace-scoped roles —\n workspace_admin, operator, viewer — with a strict hierarchy.\n `lib/rbac.ts` + `lib/auth-server.ts` centralize the policy\n layer; every mutating server action and OAuth route now\n funnels through `authorizeWorkspace(slug, minRole)` and\n returns DENIED_MESSAGE on insufficient role. Role assignments\n are themselves audited (`source=policy_change`,\n `kind=member.added | member.role_changed | member.removed`).\n New Settings → Members section with role picker, add-by-email,\n and remove affordances (workspace_admin only); last-admin\n demotion is blocked in the DB helper. UI affordance hiding\n (New agent, Run now, Delete agent, Chat-to-edit) keys off the\n current user's role; server enforcement remains the contract.\n Org-admin tier deferred until there are concrete cross-workspace\n endpoints to gate on it.\n- **RBAC-half of US-0.4-05 closed.** Role-assignment audit events\n (`member.added` / `member.role_changed` / `member.removed`) now\n carry the target user's name + email in the payload, and the\n audit UI renders them as readable rows (\"Alice · viewer →\n operator\" rather than the raw uuid). The audit-export event\n (`audit.exported`) renders the filter snapshot + row count.\n The policy-half of the AC (template version diffs, override\n events with justification) stays open until the policy\n substrate ships, since those event types don't exist yet.\n\n### Scope moves\n- **API-level deny test in CI → v0.4+.** The v0.4-02 AC asks for\n CI-verified API enforcement. Vitest deny-tests on the\n `authorizeWorkspace` funnel land in v0.4 itself\n (`web/src/lib/auth-server.test.ts`); the GitHub Actions workflow\n that would run them on every PR is in\n [`context/backlog/`](./context/backlog/USER_STORIES.md) — the\n enforcement is locked in by code + test, CI is the missing\n enforcement of the test.\n- **US-0.4-03 (org-level policy templates) → Backlog.** Needs an\n org concept (a scope above workspace) plus a generic policy\n resolver substrate; the rest of v0.4 ships cleanly without it.\n Pulls forward when a concrete customer use case lands or when\n v0.5 prep needs the substrate.\n- **New `context/backlog/` folder.** Sibling to the numbered\n phase folders; holds designed-but-unscheduled stories with\n `Moved from: vX.Y` provenance lines. Replaces the per-phase\n `Stretch (Considered, Deferred)` pattern as the home for\n stories that *don't* have a phase yet.\n- **`context/shipped/` folder.** Shipped phase folders (0.1, 0.2,\n 0.3) moved under `context/shipped/` so active phases stay\n uncluttered at the `context/` root. Docs themselves remain\n load-bearing references; only the directory layer changed.\n All cross-phase relative links updated; v0.4 → shipped uses\n `../shipped/0.X/`, shipped → v0.4+ uses `../../0.X/`, and\n sibling refs within `shipped/` stay as `../0.X/`. Root README +\n ROADMAP + a couple of source-file comments updated to point at\n the new paths.\n\n## [v0.3] — Operational surface — shipped May 2026\n\nThe day-two surface. Agents reach external services through a real\nsubstrate (no more \"the model knows how to write Slack messages but\nthe runtime can't actually call Slack\"). Operators get one screen\nper agent that answers \"how's it going?\" and \"if it's not, what's\nbroken?\" — the v0.3 phase's \"one screen, not four hours of log\nspelunking\" goal. The originally-planned rich-HITL pieces moved\nout to make room for Connections, which ate the phase honestly.\n\n### Added\n- **Composio-backed Connections substrate.** External services\n (Slack, Gmail, Google Sheets, Notion, GitHub, Linear, HubSpot,\n Salesforce, … ~1,043 in Composio's catalog) for agents to call\n at run time. Authorized once per user per workspace via\n Composio's hosted OAuth, cached as a `workspace_composio_connection`\n row keyed by `(workspace_id, user_id, toolkit_slug, name)`.\n Per-user model: each member authorizes their own toolkits;\n scheduled runs use the automation's \"Run as\" owner. The\n workspace Composio API key is itself a workspace secret\n alongside Tembo / Anthropic / OpenAI keys.\n- **Connections page (new top-level sidenav item).** Lists each\n `(toolkit, name)` slot declared by agents in the connected\n repo plus anything pre-authorized. Inline Disconnect /\n Reconnect / Rename actions per row, with toolkit logos pulled\n from Composio's catalog. \"Add another connection\" form sits at\n the bottom for pre-authorizing a slot before an agent declares\n it.\n- **Toolkit picker.** Combobox over Composio's full catalog,\n alphabetized, filter-as-you-type, name + slug side-by-side\n per row with the toolkit's logo. Catalog cached in-process for\n 1 hour.\n- **Named connection slots.** Agent spec's `connections:` accepts\n `{ name, tools }` per toolkit so the same user can hold\n multiple Gmails / Slacks / GitHubs and an agent can target a\n specific one. Canonical form is named slot + narrow tools list\n (turns on Composio's DIRECT_TOOLS preset, ~10× cheaper input\n tokens than the loose search-and-execute path).\n- **Pydantic-AI runtime pipe for Composio tools.** Python wrapper\n (`api/scripts/run_pydantic.py`) materializes a Composio session\n from the spec's `connections:` field, attaches it as an MCP\n toolset, and resolves each `(toolkit, name)` slot to the acting\n user's authorized connection. Imperative preamble prepended to\n the agent's instructions so tool-using models execute instead\n of hedging.\n- **Per-agent operational dashboard.** Health header (colored by\n 30-day failure-rate band), four stat tiles (Runs / Success rate\n / Spend / Avg duration), daily-trend bar (30-day strip with\n success / failure overlay), recent-failures grouping (top-5\n error prefixes by count, with a link to one example run each).\n Empty-history agents skip the dashboard so \"0\" tiles don't\n read as broken.\n- **Persisted run cost.** New `run.cost_usd` column populated at\n `mark_succeeded` time using a model-pricing table mirrored\n in Rust (`api/src/pricing.rs`). Cost column on the workspace\n Runs page renders with the same bar-chart background as\n Duration, scaled to the highest cost in view.\n- **Sidebar action-needed alerts.** When a repo agent declares a\n `connections:` slot the current user hasn't authorized, the\n sidebar shows \"Connect {toolkit} for {agent}\" with a direct\n authorize link. Per-user so each member sees their own gaps.\n- **Multi-workspace support.** Sidebar workspace switcher,\n multi-workspace onboarding, `/` redirect lands on the\n last-visited workspace (via `workspace_member.last_visited_at`).\n- **Automation \"Run as\" owner.** Scheduled runs use the\n automation's `owner_user_id` (defaults to creator). Owner\n picker in the automation form lists workspace members so the\n per-user connections model has a sensible answer for\n scheduled credentials.\n- **GitHub fetch cache.** `listDirectory` + `readFile` cached\n for 60s tagged per repo via Next.js fetch tags. Writes\n (`createFile` / `updateFile` / `deleteFile`) bust the tag via\n `updateTag`. Cuts the sidebar-driven scan cost.\n- **Event triggers (Composio-backed).** New `workspace_trigger`\n table binds a Composio trigger instance to an agent + owning\n user + connection slot. Per-workspace webhook endpoint at\n `/api/hooks/composio/{slug}` HMAC-verifies the inbound payload\n (`composio_webhook_secret` stored alongside the API key),\n resolves the trigger row, and enqueues a run with\n `trigger='event'`. Per-agent Triggers section on the detail\n page renders the list + a create form that takes a Composio\n trigger slug, a connection, and a JSON config. Event-driven\n runs show a purple **Event** badge on the workspace Runs page\n and the run-detail header.\n- **Agent inventory.** Workspace landing page is now a sortable\n table (Status / Name / Framework / Model / Runs 30d / Success\n / Last run) instead of a card grid. Facet pills filter by\n Active / Idle / Error / Pending / Invalid with live counts;\n free-text search across name. Pending creates + invalid agent\n files render inline as their own rows.\n- **Workspace dashboard.** `//dashboard` now mirrors\n the per-agent dashboard shape: health header banded by 30d\n failure rate, four stat tiles (Runs / Success rate / Spend /\n Avg duration), 30-day daily-trend bar, and a \"Top failing\n agents (30d)\" rollup with click-through to the latest failing\n run. Improvements counts + recent list stay below as\n secondary context.\n- **Log explorer (on `/runs`).** Search predicate extended to\n ILIKE across `error_message` in addition to user_message +\n output. Failed rows surface a two-line error excerpt inline\n so triage scans don't require a click. `/runs` now reads\n `status` / `trigger` / `agent` / `q` from URL search params\n so deep links land prefiltered.\n- **Failure-aware sidebar alerts.** \"Action needed\" rail now\n surfaces agents with at least one failure in the last 24h\n (\"Agent X failed N× in 24h → Open\") above the missing-\n connection alerts. Capped at five so a broken workspace\n can't shove the rail off-screen.\n- **Failure investigation links on run detail.** Failed-run\n detail page now offers two jumps: \"Find similar runs →\"\n (deep-links into `/runs` filtered to the agent + status=failed\n + error-prefix search) and \"View {agent} failure groups →\"\n (anchored deep link into the per-agent dashboard's grouped\n failures section).\n\n### Changed\n- **Create-agent prompt slimmed and rebuilt around Connections.**\n `buildCreateAgentPrompt` drops the verbose guidance-refresh\n block, points Tembo at the in-repo `AGENT_GUIDE.md`, tells it\n the canonical `connections:` form is named slot + narrow tools,\n and recommends defaulting to `anthropic:claude-opus-4-7` for\n tool-using agents (Opus executes; lower-tier models hedge on\n multi-step tool dances), with downgrade-to-Sonnet documented\n as the cost-optimization step once an agent is reliable.\n- **All `useActionState` forms switched to controlled inputs.**\n React 19's useActionState resets uncontrolled fields after\n each submission, including the returned-error path. Onboarding /\n repo-connect / secret-key / new-agent / run-now / automation /\n rename-connection forms all updated so a validation bounce\n doesn't wipe the user's typed input.\n- **Empty-input run default.** The Python wrapper used to\n substitute `\"Hello.\"` when a run had no user message — models\n greeted back instead of executing. New default is a directive\n (`\"Execute the job described in your instructions.\"`).\n- **Sticky sidebar.** Workspace nav stays put while the main\n column scrolls.\n- **Toolkit allowlist removed.** Earlier in the phase, TAS\n hardcoded the set of Composio toolkits it recognized. That was\n actively blocking Tembo from declaring legitimate connections\n (e.g. an email-reading agent that wanted `gmail`). Connections\n are now declared by agents, and any Composio slug is accepted.\n\n### Fixed\n- **Delete-agent UI lag.** Action redirects with `?deleted={name}`;\n the agents grid defensively filters that name from the\n rendered list AND shows a confirmation banner. Instant\n feedback even when the GitHub fetch cache hasn't propagated.\n- **Workspace secret validation accepted junk.** A literal HTML\n 404 page text once landed in a workspace's Composio API key\n field. Per-kind prefix sniff at save now catches this (`ak_`\n for Composio, `sk-` for OpenAI, `sk-ant-` for Anthropic);\n the runtime no longer 401s silently when a non-key string\n was pasted.\n\n### Scope moves\n- **HITL pause/resume + rich forms → v0.4.** Originally a v0.3\n anchor; the Connections substrate ate the phase, and the\n remaining v0.3 work (workspace-wide triage surfaces + failure\n investigation) landed in its place. HITL is the next major\n substrate piece and anchors v0.4.\n- **Workspace-wide triage surfaces → mostly shipped, residuals\n to v0.4.** Agent inventory ✓, workspace dashboard ✓, log\n explorer (extended `/runs`) ✓, failure-aware sidebar ✓.\n Topology map + tasks inbox land in v0.4 (tasks inbox depends\n on HITL anyway).\n- **Event-trigger form polish → v0.3+.** Trigger slugs are\n currently entered as free text (linked to Composio's catalog).\n Schema-driven per-trigger config forms (pulled from\n `getTriggerType`'s `config` schema) land in a later iteration.\n\n## [v0.2] — Authoring velocity — shipped May 2026\n\nThe chat-to-PR loop. A non-engineer describes an agent (or a change to one)\nin plain English; Tembo opens a pull request; the team reviews a diff.\n\n### Added\n- **Chat-to-create.** New agents start from a chat description on the\n `/agents/new` page. Tembo writes a valid agent file in the chosen\n framework's canonical shape and opens a PR. Pending creates appear as\n dashed-border cards on the agents grid until the PR merges.\n- **Chat-to-edit.** Each agent has a chat thread. \"Send to agent\" runs the\n agent with your message; \"Submit change request\" packages the message and\n hands it to Tembo, which opens a PR. Both intents share one composer.\n- **Improvement loop.** Run-detail \"Improve the Agent\" form ships free-text\n feedback to Tembo as a coding task. The opened PR carries a marker that\n lets TAS correlate merged PRs back to the improvement row. New\n `/improvements` page lists every submission with status (submitted /\n PR opened / merged / closed).\n- **Automations.** Scheduled runs via cron expressions. New `/automations`\n route with a list, create/edit form (live cron preview + next-fire in\n local time), and an enable/disable toggle. Agent detail page surfaces an\n agent's automations. Run rows show a \"Scheduled\" badge and link back to\n the automation. Single-process Node.js scheduler tick at 30s resolution,\n fires through the same `/internal/runs` path as manual runs.\n- **Runs page.** Workspace-wide run list with status / trigger / agent\n filters, ILIKE search across input + output, cursor-paginated \"Load\n more\". Whole-row click navigates to the run detail. Relative-time\n \"5m ago\" inside 24h, absolute `LocalTime` beyond. Subtle bar-chart\n background on the Duration cell scaled to the longest run in view.\n- **Dashboard.** Per-workspace landing page: active vs. all-time agent and\n run counts, weekly improvement breakdown, recent improvements feed.\n- **Run-now with input.** Clicking Run now on the agent detail page opens\n a dialog with an autofocused textarea for the user message. Empty\n submission preserves the prior \"no input\" behavior.\n- **Floating copy button** on the run-detail output card. Hover-only,\n cross-fades in over 150ms, strips the `[stop_reason]` suffix before\n copying.\n- **OpenAI provider.** Agents can declare `openai:gpt-...` models alongside\n Anthropic.\n- **AGENTS.md hierarchy.** A root `AGENTS.md` and `api/AGENTS.md` join the\n existing `web/AGENTS.md`. Each coding-request prompt to Tembo also pushes\n current TAS-managed guidance files into the customer's workspace repo:\n root `AGENTS.md`, `agents/AGENTS.md`, and per-framework `AGENT_GUIDE.md`\n files are refreshed on drift; customer-managed\n `ADDITIONAL_AGENT_INSTRUCTIONS.md` is created once, never overwritten.\n- **Settings → Sync agent guidance.** One-click bootstrap or refresh of\n the guidance files into the connected workspace repo, for repos whose\n agents predate the auto-bootstrap.\n- **LocalTime hover-to-UTC.** Datetime renders local with the local-tz\n abbreviation by default; hover/focus cross-fades to the same instant\n in UTC over 500ms. Uses inline-grid so the container sizes to the\n wider string and surrounding text doesn't jump.\n\n### Changed\n- **Passthrough runner.** Both supported frameworks now shell out to the\n upstream tool — Cargo AI via the bundled `cargo-ai` CLI; Pydantic AgentSpec\n via the real `pydantic-ai` library in a bundled Python venv. The Rust API\n no longer hand-rolls provider calls.\n- **Markdown output.** Agent output renders as markdown by default.\n- **Feedback → Improvement rename** everywhere (DB table, routes, UI copy).\n The PR-correlation marker `TAS-Feedback-ID:` is kept as a wire-format\n constant for back-compat with in-flight PRs.\n- **`/agents/new` simplified.** Removed \"From template\" and \"Paste\n definition\" tabs; chat is the only path now. Lib code for the removed\n paths (`createAgentFromTemplate`, `createAgentFromContent`,\n `commitAgentFile`, starter renderers) dropped.\n- **Base UI primitives.** New `Select` component built on `@base-ui/react`.\n `Badge` padding bumped, `Input` height bumped, framework label shortened\n to \"Pydantic\" / \"Cargo AI\".\n\n### Scope moves\n- **US-0.2-08 (event-driven triggers) → v0.3 US-15.** Depends on the\n Connections substrate v0.3 owns; building a one-off github-only\n webhook receiver in v0.2 would have been a snowflake.\n- **US-0.2-06 (HITL pause/resume) → v0.3 US-13b.** Merges cleanly with\n v0.3's rich-HITL-forms work; splitting it across phases meant v0.3\n would have to immediately rewrite the v0.2 surface.\n- **US-0.2-03/04 (PR policy) → backlog.** Blocked on the Tembo Coding\n Agent Platform shipping a direct-commit mode; today CAP always opens\n a PR, so there's no auto-merge surface to wire.\n\n## [v0.1] — Foundation — shipped May 2026\n\nThe trustworthy floor: self-hosted deploy, identity, repo connection, runs.\n\n### Added\n- Docker-compose deploy: Next.js 16 web + Rust axum API + Postgres.\n- Auth via better-auth + Google OAuth (email/password disabled, in-app\n instructions for swapping providers).\n- GitHub OAuth repo connection — token stored AES-256-GCM-encrypted on the\n workspace row.\n- Agents listed from the connected repo as a 3-column card grid (last run\n status, framework + model badges, search). Two framework families\n supported: **Pydantic AgentSpec** and **Cargo AI**, each under their own\n `agents//` subfolder.\n- Create-agent flow (from template or paste, with framework picker).\n- Manual runs against Anthropic Claude (Opus / Sonnet / Haiku). Output\n streams to a run detail page with status, model, queued/started/duration,\n and token consumption + approximate cost.\n- Soft-delete + restore for agents (commits to the repo on both ends;\n deletion record retained for audit).\n- Per-workspace favicon picker (default set + custom upload).\n- Theme picker in settings: System / Light / Dark mode toggle, eight\n built-in presets (Light, Paper, Pure Light, Dark, Midnight, Forest,\n Ember, Blackout), local-only persistence." + "body": "All notable changes to Tembo Agent Studio. Format loosely follows\n[Keep a Changelog](https://keepachangelog.com/en/1.1.0/).\n\n**Versioning:** releases use a year.month [CalVer](https://calver.org/) tag plus\na release counter — `vYYYY.M.N`. `YYYY.M` is the year and month; `N` increments\nonce per release within that month and is **not** the day of the month (the\nearliest 2026 tags happened to line up with the date, but it's just a counter).\nThe `0.1`–`0.4` entries below are phase numbers from\n[`ROADMAP.md`](./ROADMAP.md), which remain the *construction* milestones;\nthey are no longer release versions. Phase scope now lives in\n[GitHub Issues](https://github.com/tembo/agent-studio/issues?q=is%3Aissue+label%3Aenhancement).\n\n## [Unreleased]\n\n## [v2026.8.3] — Dashboard load-time fix, duplicate-migration CI guard — shipped 2026-08-18\n\n### Fixed\n- **The workspace dashboard took seconds to render.** Every visit blocked on a\n full GitHub reconciliation of open improvements before any database query\n ran: one PR fetch per open improvement — unbounded, so a large backlog drew\n secondary rate-limit 403s whose answers were then discarded — plus two calls\n to GitHub's ~30 req/min search endpoints, issued back-to-back. The scan now\n runs its three paths concurrently, caps PR fetches at 8 in flight, and\n re-runs at most once a minute per workspace. Improvement PR state is\n correspondingly at most a minute stale: a PR you merged moments ago can take\n that long to show as `Merged`.\n- **The dashboard's 30-day activity chart loaded one row per run.** The\n workspace-wide trend spans every agent, so it shipped the entire 30-day run\n set to the web tier to run-length-encode in JavaScript. The encoding now\n happens in SQL and returns one row per band the chart actually draws.\n\n### Changed\n- CI fails a pull request when two migrations share a version number — the\n defect that made v2026.8.1 unable to boot.\n\n### Dependencies\n- Routine Dependabot bumps across web, api, docs, and CI actions (better-auth,\n cron-parser, vite, eslint-config-next, `@types/node`, thiserror, base64,\n Astro, github/codeql-action).\n\n## [v2026.8.2] — migration 0069 collision fix, per-user MCP OAuth, durable Pydantic runs — shipped 2026-08-17\n\n### Added\n- **Per-user OAuth for the TAS MCP server.** Claude Web, Claude Desktop, and\n other hosted MCP clients can now discover TAS OAuth metadata, register\n dynamically, complete S256 PKCE, select a workspace, and receive refreshable\n tokens bound to the signed-in user's live membership and role. Existing\n `tas_` API keys remain\n supported for Claude Code and scripts.\n- **Durable Pydantic runs.** Pydantic executions now persist their immutable\n launch envelope and checkpoint typed message history at every model/tool node.\n Runs interrupted by an API or host restart resume from the last acknowledged\n checkpoint, preserve the original run clock and completed-step usage, and\n show a **Resumed** indicator on run detail. Cargo AI and legacy runs remain\n explicit interruption failures because they have no safe replay boundary.\n\n### Fixed\n\n- **v2026.8.1 could not apply database migrations.** That release shipped two\n migrations both numbered `0069` (`workspace_user_secret` and\n `instance_admin`), so the api recorded one and crashed applying the other —\n and afterwards no version could boot against the touched database.\n `instance_admin` is now `0070`. Upgrading to this release is the fix; if a\n v2026.8.1 api already ran against your database, first check\n `SELECT description FROM _sqlx_migrations WHERE version = 69;` — if it says\n `instance admin`, run `UPDATE _sqlx_migrations SET version = 70 WHERE\n version = 69;` once before upgrading (the file was renamed with identical\n content, so the recorded checksum already matches). If it says\n `workspace user secret`, or there is no row 69, no manual step is needed.\n- **Chat-to-PR tasks could drift to the wrong repository.** Tembo agent tasks\n now carry an explicit scope block pinning them to the workspace's connected\n agents repo and default branch, so session context mentioning other repos or\n prior PRs no longer redirects the change.\n- **Claude showed the Railway logo for the TAS connector.** The MCP initialize\n response now advertises Tembo's display name and a public PNG icon, the icon\n directory bypasses the session gate, and `/favicon.ico` provides a fallback\n for clients that use conventional origin favicon discovery.\n\n## [v2026.8.1] — Password management for email/password instances, in-app instance admins, personal Tembo identity — shipped 2026-08-04\n\n### Added\n- **Lost / reset / change password on email/password instances.** TAS is\n SMTP-free, so recovery is admin-driven: a workspace admin generates a\n one-time reset link (1-hour expiry) from the member's detail page and\n shares it out-of-band; the link lands on a new public `/reset-password`\n page. Signed-in users change their own password under Settings →\n Account. Both revoke other sessions. None of this renders when an OAuth\n provider is configured — credentials live at the identity provider there.\n- **Instance admins managed in-app.** Instance Settings now lists and edits\n instance admins (stored in the database, unioned with the\n `INSTANCE_ADMIN_EMAILS` env bootstrap); the sign-up gate honors both\n sources, so admin changes no longer require a redeploy.\n- **Personal Tembo identity with workspace fallback.** Chat-to-PR authoring\n can use a per-user Tembo API key (Settings → Tembo), falling back to the\n workspace key — PRs and sessions attribute to the person, not the shared\n workspace identity.\n- **Built-in run date/time tool.** Every Pydantic agent can call\n `get_run_datetime` without adding a connection. It returns the stable run-start\n instant and local date/time fields for a requested IANA timezone, giving\n scheduled agents a reliable basis for relative windows and date-based dedup.\n\n### Fixed\n- **Invitations now resolve on email/password instances.** Credential\n sign-ups always carry `emailVerified=false` (no IdP, no SMTP), and the\n invite-to-membership step required a verified email — so invitees could\n sign up but landed workspace-less. On email/password instances the\n invite-gated sign-up itself is the authorization, and invites now resolve;\n instances with an OAuth provider keep the strict IdP-verified check.\n\n### Changed\n- **Continuous deploys now cover all Tembo-managed instances.** The internal\n pipeline that tracked `main` on the dogfood box now fans out per-instance\n (each with its own Railway project token) — self-hosted customer\n instances remain pinned to release tags like this one.\n\n## [v2026.7.4] — Inbox reading view for digests, markdown context + run links, quieter Slack threads — shipped 2026-07-24\n\n### Added\n- **Inbox item detail: markdown context + run link.** Context fields that\n contain Markdown (agent digests) now render formatted instead of as raw\n text, and the header links to the run that produced the item.\n- **Newsletter-style reading view for text-only inbox items.** Any text-only\n context (the `{ text }` shape `produce_inbox_item` stores for plain-string\n contexts) now renders as an unboxed full-width document at reading size\n (18px/1.6) with no CONTEXT/TEXT chrome — the markdown sniff only picks the\n renderer (Markdown vs pre-wrap), so table-only markdown can no longer fall\n back to the boxed fields view. GFM tables are recognized and wide tables\n scroll horizontally. Structured contexts keep the boxed labeled-fields view.\n- **Links rollup on inbox items.** The Links section moves below the content\n and collapses behind a \"Links (N)\" disclosure past 5 entries, so a digest\n citing 20 sources no longer opens with a wall of links while short triage\n lists stay fully visible. `produce_inbox_item`'s descriptions now steer\n producers to inline markdown sources for narrative digests.\n\n### Fixed\n- **Slack: untagged thread replies no longer trigger the which-agent menu.**\n A plain reply inside a bot DM thread (e.g. answering a daily brief with\n `Y`) used to post the \"Tell me which agent to run…\" menu on top of any\n custom listener already answering that thread. Untagged thread replies are\n now left to the thread's listener; explicit `@agent` mentions in a thread\n still launch their agent, and plain top-level DMs are unchanged.\n- **Internal deploy CI: Railway GraphQL errors now fail the job.** Railway\n reports failures in-band with HTTP 200, so `curl -f` never tripped — an\n expired plan left the deploy step green while deploying nothing.\n\n## [v2026.7.3] — pydantic-ai 2.x runner, WebSearch run + agent-change dispatch fixes, catalog batch 3 — shipped 2026-07-20\n\n### Added\n- **Native MCP catalog batch 3: 136 more providers.** Harvested from the\n official MCP registry (54k entries swept), the claude.com/connectors\n directory, and community remote-MCP lists; every endpoint live-probed\n (MCP `initialize` → `/.well-known/oauth-protected-resource` →\n auth-server metadata → `registration_endpoint`) on 2026-07-18:\n - **TAS-managed DCR (123):** sales/GTM (Outreach, Salesloft, ZoomInfo,\n Lusha, Hunter, Instantly, Crossbeam, Harmonic, Chili Piper, Day AI,\n Clarify, Staircase AI), support/CX (Zendesk, Help Scout, Gorgias, Plain,\n Lorikeet, Unthread, Enterpret, Dovetail, Missive), meetings (Otter.ai,\n Grain, Krisp, Circleback, tl;dv), finance (Ramp, Brex, Mercury,\n Expensify, Navan, Carta, Digits, GoCardless, Mercado Pago), market\n intelligence (PitchBook, Morningstar, CB Insights, Quartr, Daloopa,\n Consensus), HR/recruiting (Gusto, Deel, Ashby, Workable, Metaview,\n Indeed, Udemy Business), compliance/e-sign (Vanta, Drata, SignNow),\n productivity/design (Figma, Miro, Lucid, Productboard, Aha!, Shortcut,\n Todoist, Teamwork, Calendly, Superhuman Mail, Craft, Mem, Gamma, Pitch,\n Eraser, Jotform, Typeform, SurveyMonkey, Egnyte), marketing/content\n (Mailchimp, Customer.io, Ahrefs, Semrush, Cloudinary, Contentful,\n Sanity, Wix, WordPress.com, GitBook, Mintlify, DeepL), dev/infra\n (GitLab, Supabase, Netlify, Heroku, Buildkite, Grafana, New Relic,\n Honeycomb, incident.io, Rootly, BugSnag, LaunchDarkly, PlanetScale,\n Prisma Postgres, InstantDB, Algolia, Statsig, Postman, Semgrep, WorkOS,\n Stytch, Mux, Knock, Lovable, Retool, Telnyx, Jam, Globalping), data/AI\n (Airbyte, MotherDuck, Monte Carlo, Atlan, Hugging Face), and\n automation/web (Zapier, Make, IFTTT, Exa, Tavily, Firecrawl, Apify,\n Bright Data).\n - **Bring-your-own OAuth app (12):** DocuSign, Xero, Front, Smartsheet,\n MongoDB Atlas, CircleCI, Chargebee, BigQuery (Google manual client,\n like Gmail), Ironclad, Harvey, Tableau, Shopify.\n - **API token (1):** Render (API key as Bearer, like GitHub).\n - Agent Library categories now recognize the new providers, and the\n long-tail **ATS / recruiting**, **HRIS**, **E-signature**, and\n **Survey** categories flip to connectable.\n - Not added (with reasons): per-tenant instance-scoped servers\n (Salesforce, Snowflake, Databricks, ServiceNow, NetSuite, Glean, dbt,\n Elastic…), OAuth `client_credentials`-only (Plaid), unauthenticated /\n docs-only servers, and vendors with no hosted server (Workday,\n Rippling, Okta, Snyk, Perplexity, Loom, Fivetran).\n\n### Fixed\n- **WebSearch agent runs on Claude no longer fail with a 400.** Anthropic now\n routinely pauses long server-tool turns (`stop_reason: pause_turn`), which\n pydantic-ai 1.x replayed malformed — every run of a `WebSearch`-capability\n agent died with *\"`web_search` tool use … without a corresponding\n `web_search_tool_result` block\"* from 2026-07-16 on. The bundled runner is\n now pydantic-ai **2.13.0**, which continues paused turns natively. Also\n drops the sequential-tool-calls default for WebSearch agents on Anthropic\n models (the API rejects `disable_parallel_tool_use` combined with the new\n web_search tool's programmatic tool calling).\n- **Agent-change submissions work again.** Tembo CAP renamed its public task\n route from `/public-api/task` to `/public-api/session` (2026-07-16) with no\n alias, so every chat-edit / improve / create dispatch since then failed with\n *\"invalid request path\"*. TAS now calls the new endpoint.\n- **Agent-change dispatch errors are self-describing.** The REST/MCP path\n reported CAP failures as an opaque `(http)`; it now includes the upstream\n HTTP status and response body.\n\n### Changed\n- **Runner: pydantic-ai 1.102.0 → 2.13.0.** Spec `instrument: true` and\n ScaleDown compression now attach as pydantic-ai capabilities\n (`Instrumentation` / `ProcessHistory`); behavior is otherwise unchanged.\n- **Rust OAuth-origin allowlist is now generated from the web catalog.**\n `api/src/native_oauth_allowlist.rs` is produced from `MCP_PROVIDERS`\n (`web/src/lib/mcp-providers.ts`) by `npm run gen:allowlist`, replacing the\n hand-maintained duplicate (~360 lines of consts + tuples) in\n `native_oauth.rs`. The allowlist-sync vitest is now a staleness check on the\n generated file instead of a per-provider drift detector — the failure mode\n where a catalog entry lands without its Rust twin (the Dialed regression)\n is eliminated rather than just alarmed on. No behavior change: the generated\n table is semantically identical to the old hand list (184 origins).\n\n## [v2026.7.2] — Native MCP catalog expansion, connection search, Zoom, inbox delete — shipped 2026-07-15\n\n### Added\n- **Large native MCP catalog expansion.** ~30 more hosted OAuth MCP providers\n verified via live discovery (Anthropic knowledge-work-plugins +\n `/.well-known` probes):\n - **TAS-managed DCR:** PostHog, Stripe, Vercel, Canva, ClickUp, Close, Sentry,\n Mixpanel, Granola, Dropbox, Webflow, Cloudflare, Neon, Cal.com, Klaviyo,\n PayPal, Square, Airtable, Railway, Resend, Hex, Pendo, Similarweb, Datadog,\n Common Room\n - **API token:** GitHub (PAT), X (App-only Bearer)\n - **Bring-your-own OAuth app:** Slack, Gong, Box, PagerDuty, Zoom\n (`mcp.zoom.us`; `client_secret_basic` supported for manual token exchange)\n- **New connection search.** Landing page search spans Native MCP, Composio\n toolkits, and manual credentials — jump straight to a provider. Composio is\n ranked and styled as **last resort** when a native option exists (Recommended\n vs Fallback sections, badges, quieter type card).\n- **Native MCP picker table.** Connections → New → Native MCP is a searchable,\n filterable, sortable table (category + auth filters, Connect link).\n- **Delete dismissed inbox items.** On the Inbox **Dismissed** facet, multi-\n select and permanently **Delete** (owner-scoped). Active facets still mass-\n **Dismiss**; *Done* stays unselectable.\n\n### Fixed\n- **Run detail header cost** now prices prompt-cache halves (0.1× read / 1.25×\n write) instead of undercounting when caching engages — aligned with the step\n footer.\n\n## [v2026.7.1] — Agent Library, knowledge-work skills + 9 MCP providers, Sonnet 5 default, new Tembo mark — shipped 2026-07-08\n\n### Added\n- **Agent Library.** A browsable catalog of ~124 ready-made starter agents\n across work areas (Sales, CS, RevOps, Finance, Legal, Data,\n Product/Engineering, IT…), ranked **connection-aware** so the starters you\n can actually run — given what you've connected — lead. Clicking a starter\n pre-fills the New Agent form and the existing Tembo Coding Agent flow turns\n it into a spec + PR. Starters live as one-file-per-starter YAML read at\n runtime, composed from shared archetype prompts. Public + in-app docs page.\n- **Nine more native MCP providers.** Notion, Intercom, Atlassian (Jira),\n Asana, monday.com, Guru, Fireflies, Amplitude, and Apollo — all confirmed\n Dynamic Client Registration, so they're TAS-managed connections with no\n per-customer OAuth app and are enabled by default in the picker. Harvested\n from Anthropic's\n [knowledge-work-plugins](https://github.com/anthropics/knowledge-work-plugins)\n connector catalog (batch 1).\n- **Browse + install Anthropic knowledge-work skills.** The Skills install\n page now surfaces that repo's ~95 Agent Skills as a catalog — filter by\n work area, search, install with one click. Their `SKILL.md` format is\n exactly what TAS already mounts, so agents pick up role-specific domain\n expertise alongside the matching library starters.\n- **Agent Skills documented for the Coding Agent.** `/for-agents` guidance\n now covers authoring and consuming Agent Skills.\n\n### Changed\n- **New agents default to Claude Sonnet 5** (`anthropic:claude-sonnet-5`).\n Model guidance flips the \"start on Opus, then downgrade\" playbook — Sonnet 5\n is agentic enough to be the starting point, with Opus 4.8 / Fable 5 reserved\n for the hardest work. Sonnet 4.6 is retired from examples, docs, the sample\n agent, and the CAP prompt.\n- **New Tembo T mark.** The app and docs favicons (and the README badge) swap\n the old elephant-trunk logo for the new blocky-T mark, with cache-busting so\n stale favicons refetch.\n- README refreshed to clarify setup and the project overview.\n\n### Fixed\n- Dropped the redundant \"Create an agent that handles this task:\" prefix on\n library-seeded agent requests.\n\n## [v2026.6.29] — More MCP providers + confidential/instance connect, Clerk triggers, schedule-from-description, graceful drain — shipped 2026-06-30\n\n### Added\n- **Four more native MCP providers.** Amplemarket, Clay, Avoma, and Metabase\n join the native-MCP catalog and connect in a couple of clicks.\n- **Confidential & instance-based MCP connect.** Two new connection shapes widen\n what TAS can authorize: **confidential Dynamic Client Registration** for\n providers that require a confidential OAuth client (this unblocked Avoma), and\n **instance-based providers** where the user supplies part of the server URL —\n e.g. your own Metabase host. Both keep the SSRF guards of the existing flows.\n- **Optional API key on a native-MCP connection.** A connection can now carry a\n supplementary API key alongside its OAuth token (some providers gate write\n actions behind a scoped key the MCP token can't grant), with a per-provider\n note explaining **why** and **which scopes** are needed.\n- **Trigger agents from Clerk webhooks.** Inbound Clerk events (Svix-signature\n verified) can fire an agent; the webhook signing-secret UI is now\n provider-agnostic so other signed-webhook sources slot in.\n- **Scriptable run cancel.** `POST /api/v1/runs/[id]/cancel` kills an in-flight\n run from the API, complementing the in-app Stop button.\n- **Auto-create a schedule from the agent description.** When you create an agent\n whose description names a recurring schedule (\"every weekday at 9am\"), TAS\n parses it and creates an enabled automation alongside the agent. Conservative —\n prose that merely mentions a time doesn't trigger one.\n- **Timezone-aware automations (DST-correct).** Automations store an IANA\n timezone and the scheduler evaluates each cron in that zone, so a wall-clock\n schedule tracks daylight saving. The form gains a timezone picker (defaulting\n to your browser zone); existing automations keep firing in UTC.\n- **Agents-owned on the Team dashboard.** Each member row shows how many agents\n they own, with a count of unowned agents so nothing falls through the cracks.\n- **Copy button on the Definition tab** and **expandable tool-call errors** in\n the run step timeline.\n\n### Changed\n- **Graceful shutdown.** On deploy/restart the api now **drains in-flight runs**\n before exiting instead of killing them mid-execution.\n- The new agent file is committed next to the user's request, and inbox guidance\n softens the OAuth-token-for-REST advice (an item now also accepts string\n context).\n\n### Fixed\n- **Prompt-cache token accounting.** Stopped double-charging cached prompt tokens\n and fixed live per-step input tokens under-reporting mid-run.\n- **Connect flows.** Amplemarket and Metabase reject the auto-appended\n `offline_access` scope — no longer requested; an unset auth mode is treated as\n DCR so those connections stay editable; runs are registered before the\n subprocess spawns (no orphaned \"running\" rows on a crash at startup).\n- **Sidebar.** Failing-agent alerts are scoped to your own runs (a teammate's\n failure no longer nags you), and the \"Action needed\" header no longer lingers\n over an empty section once its cards are dismissed.\n- **LinkedIn (and any manual-credential) logo** now renders on the connections\n list, detail, and picker instead of a generic glyph.\n\n## [v2026.6.28] — Agent web search, inbox triage + links, self-documenting tool reference — shipped 2026-06-25\n\n### Added\n- **Agent web search.** Agents can now actually search the web by declaring\n `capabilities: [WebSearch]` — it maps to pydantic-ai's provider-adaptive web\n search (native on Anthropic/OpenAI, local fallback otherwise). The capability\n was documented but silently ignored by the runner before.\n- **Self-documenting tool reference.** The `/for-agents` reference now publishes\n each native-MCP tool's full **parameter schema** (name / type / required /\n description), not just a one-line description — so an agent author (and Tembo\n CAP) can discover a tool's exact arguments. The `tembo-agent-studio` reference\n is served without a token (its tools are TAS's own public API), and an instance\n can opt the whole reference public via `TAS_FOR_AGENTS_PUBLIC`.\n- **Inbox links.** An agent can attach a clickable **Links** list to one inbox\n item via `links: [{ label, url }]` on `produce_inbox_item` — e.g. the top 10\n Linear tickets behind a single triage task. Links are also **auto-extracted**\n from an item's proposed text (Markdown + bare URLs) and context payload, so the\n list populates even when the agent didn't set the field. http(s)-only, deduped,\n capped.\n- **Faster inbox triage.** Resolving an item now **advances to the next** one to\n review (with an \"N more in your inbox\" counter); the index gains **multi-select\n mass-dismiss**; and **Dismiss** is now always available on the item detail page\n (previously hidden when the agent supplied one-click options).\n\n### Changed\n- **Tool caches auto-refresh.** Every native-MCP + Composio connection's cached\n tool catalog now re-syncs on each deploy (and daily) instead of requiring a\n manual Connections → Refresh — so new/changed tools (and their schemas) appear\n on their own. Throttled so restarts don't re-storm provider APIs.\n- **Agent ownership on first run** and the marketing landing copy refresh.\n\n### Fixed\n- **Pending agent-create ghost cards.** A chat-to-create whose commit didn't\n carry the reconcile marker could sit \"Pending\" forever and couldn't be\n dismissed; creates now auto-reconcile once the agent file lands in the repo,\n and Dismiss clears direct-commit creates too.\n- **Inbox checkbox hit area** — a near-miss on the row checkbox no longer opens\n the item instead of toggling selection.\n\n### Security\n- **CodeQL batch** — least-privilege workflow `GITHUB_TOKEN`, complete\n markdown-table escaping, and log-injection hardening.\n- **ReDoS fix** — the inbox link-extraction trailing-punctuation trim no longer\n uses a backtracking-prone anchored regex on agent-supplied URLs.\n\n## [v2026.6.27] — Stop a run, security hardening, agent owners + Definition history — shipped 2026-06-23\n\n### Added\n- **Stop a running run.** A red **Stop run** button on the run detail page kills\n an in-flight (queued/running) run: it transitions to a dedicated new\n `cancelled` status (distinct from `failed`, so killed runs stay out of failure\n dashboards/badges) and the api SIGKILLs the run's subprocess. Operator+ only.\n- **Definition tab now shows every version.** The agent's Definition tab renders\n the live draft plus every promoted stable version (switchable), and a\n **History** section listing every commit of the spec file on GitHub — short\n hash, date, and author — each linking to that version on GitHub.\n- **Agent ownership.** A repo-committed agent with no owner is auto-assigned to\n the person who first runs it (chat-created agents already had an owner), so the\n Mine/Starred views and Locked/Fork rules attribute correctly.\n- **Marketing homepage for the docs site.** The docs root is now a restrained\n splash landing page (replacing the bare \"Redirecting…\"), including a FAQ on how\n TAS differs from Claude Managed Agents and Claude Cowork, and a live GitHub\n star count in the header.\n\n### Changed\n- **Orphaned runs are reconciled on api boot.** A run executes as an in-memory\n task owning a subprocess, so any run still `queued`/`running` when the api last\n stopped (crash, deploy, restart) was orphaned and hung in `running` forever.\n The api now marks such rows `failed` on startup with a clear reason. (Durable,\n resumable execution remains the larger [#170](https://github.com/tembo/agent-studio/issues/170) effort.)\n\n### Security\n- **Invites are honored only for IdP-verified emails** ([#47](https://github.com/tembo/agent-studio/issues/47)) — an OAuth sign-in\n whose provider didn't assert `email_verified` no longer auto-joins a workspace\n by matching a pending invite.\n- **OAuth state now has a TTL** ([#46](https://github.com/tembo/agent-studio/issues/46)) and the **permissive CORS layer was dropped\n from the api** ([#48](https://github.com/tembo/agent-studio/issues/48)) — it served only bearer-gated server-to-server routes,\n so the open CORS was needless attack surface.\n- **Stopped logging CAP prompt payloads** ([#44](https://github.com/tembo/agent-studio/issues/44)) and **gated audit-log export on\n admin** ([#43](https://github.com/tembo/agent-studio/issues/43)).\n- Overrode `hono` to `>=4.12.25` to clear Dependabot alerts ([#206](https://github.com/tembo/agent-studio/pull/206)).\n\n### Fixed\n- **Inbox privacy** — the Tasks Inbox was showing every member's items to all\n members. Items are now scoped to their owner (the run's acting user, or the\n human filer), with reads, the sidebar badge, and mutations all owner-scoped.\n\n### Dependencies\n- Routine Dependabot bumps across web, api, docs, and CI actions\n (better-auth, lucide-react, cron-parser, tower-http, Astro, `@types/node`,\n `@tailwindcss/postcss`, actions/checkout).\n\n## [v2026.6.26] — Agent stars + forking, unified Automations, Locked agents — shipped 2026-06-20\n\n### Added\n- **Per-agent \"Locked\" toggle.** Workspace admins can lock a governed agent\n (e.g. regulated drafting): its in-app edits — Chat to edit, Improve, Fork, and\n correction/learning capture — are removed and its Versions / Activity /\n Learning history is hidden, so it changes only through direct repo PRs. Set on\n the agent's Settings tab (admin-only) and audited on change.\n- **Unified agent Automations tab.** An agent's Automation tab now lists its\n schedules, event triggers, and inbound webhooks in one sortable, filterable\n table (matching the workspace Automations list), with a **New automation**\n type picker (Schedule / Event trigger / Webhook) in place of the separate\n inline forms.\n- **Agent visibility — stars + forking.** Star agents (☆ on each row) to curate\n a personal list; the agents page defaults to **Mine + Starred** (agents you own\n or starred) with a **View all** toggle, so big teams aren't staring at\n everyone's agents. And **Fork** any agent into your own editable, owner-prefixed\n copy (`sales-gen` → `ryw.sales-gen`) — no name collisions, owned by you, shares\n the original's tools module until you change it. New `agent_star` table; agent\n names may now carry one optional `.` owner prefix.\n- **One-command sandbox bring-up** — `./scripts/dev-up.sh` writes a dev `.env`\n (email/password sign-in, random secrets), boots Postgres + api + web via Docker\n Compose, and seeds an instance-admin login you can use immediately. Plus a\n `tembo.nix` (Rust toolchain on top of the sandbox's preinstalled Node/Docker)\n so [Tembo sandboxes](https://docs.tembo.io/features/sandbox/overview) and\n snapshots have what the build needs.\n- **Local sample agents for dev** — when a workspace has no connected GitHub\n repo and `TAS_LOCAL_AGENTS_DIR` is set, agents load (read-only) from that\n directory instead of GitHub. `docker-compose.yml` mounts the repo's `./agents`\n and enables it by default, so the bundled samples list, view, and **run** with\n no repo or PAT. Chat-authoring / improvements (which open PRs) still need a\n connected repo.\n\n### Fixed\n- **Composio connection name mismatch** no longer triggers a false \"Action\n needed\" prompt (or a failed run): when an agent pins a toolkit slot by a name\n you authorized under a different one, your single active connection for that\n toolkit is now used regardless of the declared name — matching native-MCP.\n- **Local sample agents** render without a connected repo — the workspace home\n and agent pages no longer redirect to repo onboarding when\n `TAS_LOCAL_AGENTS_DIR` is set.\n\n### Security\n- **Encrypted secrets are bound to their row** (AES-GCM AAD), so a ciphertext\n blob can't be moved to another row and still decrypt. Non-breaking (versioned\n blob; existing ciphertext keeps decrypting). Covers workspace secrets, native\n + Composio connection credentials, OAuth client secrets, Slack tokens, and\n webhook / API-key tokens.\n- **Workspace favicon route** now requires membership — unknown slugs,\n unauthenticated, and non-member requests all return the generic default,\n closing a workspace-existence probe.\n\n### Documentation\n- **Example Agents** — a new docs page of copy-paste, connection-agnostic\n agent-creation prompts (email triage, ticket/issue roundup, CRM tasks, daily\n task list). Paste one into chat-to-PR authoring and it adapts to whatever\n you've connected — generating one agent per matching service.\n\n## [v2026.6.25] — Email + password quickstart sign-in, docs refresh — shipped 2026-06-19\n\n### Added\n- **Email + password quickstart sign-in.** When no OAuth provider (Google /\n Microsoft / OIDC) is configured, the login screen now offers email + password\n — so a fresh instance is reachable with zero OAuth-app setup. Sign-up stays\n gated to `INSTANCE_ADMIN_EMAILS` / invited emails, and configuring any OAuth\n provider turns email/password off automatically (OAuth becomes the path).\n\n### Documentation\n- **New Tasks Inbox guide** — how items are produced, the action buttons that\n act in the source (Complete / Reply / Send and Archive / Archive), snooze,\n terminal dismiss, the learning loop, and the producer-side fields for agent\n authors.\n- **Fuller agent-spec reference** (Authoring agents) — documented\n `model_settings`, `request_limit`, `retries`, `instrument`, and `skills`.\n- **Connections** — the native-MCP catalog (TAS-managed vs bring-your-own OAuth\n app), the **Manage providers** setup for HubSpot/Gmail, and Gmail's Google\n Developer Preview gate.\n- **Introduction + README** — now describe the full *definition → run → act\n (human-in-the-loop Tasks Inbox) → adapt* loop, and correct the principle to\n **\"every change is a commit\"** — a pull request by default, or a direct commit\n in YOLO mode (the old \"every change is a PR\" predated YOLO delivery).\n- **Changelog page** — cleaner release headers (no brackets / shipped-date) and\n an H2-only \"on this page\" TOC.\n- **Roadmap** — pruned ideas that have since shipped (adaptive corrections loop,\n Tasks inbox, direct-commit / YOLO mode).\n\n## [v2026.6.23] — Tasks Inbox actions: act in the source — shipped 2026-06-18\n\n### Added\n- **Act on inbox items in their source system** — option buttons now run the real\n action on click, not just clear the item:\n - **Complete** a task in Dialed / Attio / Linear via a generic **native-MCP\n inbox executor** (the producing agent declares the tool + args; it runs on\n the clicking user's connection).\n - **Send / Send and Archive / Archive** for Gmail via a **Composio inbox\n executor** — Send replies and keeps the thread in your inbox, Send and Archive\n replies then files it out, Archive files without replying. Replies use an\n editable suggested draft (the LinkedIn pattern).\n- **Linear native-MCP provider** (`mcp.linear.app`, TAS-managed OAuth) — the\n Linear tasks agent moved off Composio onto it.\n- **Gmail native-MCP provider** — a manual / bring-your-own Google OAuth app (like\n HubSpot), with in-app setup guidance on Connections → Manage providers (redirect\n URI, the Gmail-specific API + scope steps, docs link). Google currently gates the\n Gmail MCP server behind its Developer Preview program, so Gmail can alternatively\n run through Composio.\n- **`gmail-tasks` email-triage agent** — surfaces your top starred/important emails\n into the Inbox (capped, deduped) with a deep link and a suggested reply.\n- **Deep links on inbox items** — an \"Open in ↗\" link to the underlying\n Dialed task / Linear issue / Attio record / email thread (new `url` field).\n- **Snooze + Dismiss escapes** on inbox items, with per-agent control over which\n clear actions appear (e.g. Gmail uses Archive instead of Dismiss).\n\n### Changed\n- **Inbox source shown as a provider logo** in the list + item detail (was the raw\n lowercase word); the technical Type column/badge is gone.\n- **Sidebar Inbox badge stays live** — polls the active count so items an agent\n produces in the background appear without a manual refresh.\n- **Task agents surface source content faithfully** — `dialed`/`attio`/`linear`/\n `gmail` run with ScaleDown off (no lossy compression of data they copy verbatim)\n and prioritize their queues (Linear: triage → in-review → in-progress → todo →\n backlog; Gmail: starred first; etc.).\n\n### Fixed\n- **Dismiss is terminal** — a re-running agent can no longer drag a dismissed item\n back into the Inbox (the reopen-on-new-activity path now skips dismissed rows).\n- **Inbox actions tolerate a connection-name mismatch** — fall back to your sole\n active connection of the provider type when the agent's declared name differs.\n- **Learning-mode checkbox no longer reverts after Save** — it revalidated the\n wrong tab and never re-synced to the saved value.\n- **ScaleDown** now treats prior history as context and the new turn as the query\n (per the API), and safely compresses bulky prior tool outputs.\n- **LinkedIn thread list pagination** uses the provider's real opaque cursor.\n\n## [v2026.6.22] — ScaleDown prompt compression + agent cost/run — shipped 2026-06-18\n\n### Added\n- **ScaleDown prompt compression.** Optionally route bulky prompt/context through\n [ScaleDown](https://scaledown.ai) to cut frontier-model tokens. Set a ScaleDown\n key under Settings → LLM Providers, then opt in per agent with `scaledown: off |\n prompt | aggressive`. `prompt` compresses the static instructions once\n (cache-friendly); `aggressive` also compresses bulky history blocks each turn,\n memoized so Anthropic prompt caching keeps working. Best-effort end to end — any\n ScaleDown failure falls back to the original text, so it never fails a run.\n Savings show on the run detail (\"5.1K → 1.8K tokens\").\n- **Avg cost/run on the agents table.** A new sortable column showing each\n agent's average estimated USD cost over its costed runs in the last 30 days.\n- **`request_limit` agent-spec field** — cap an agent's model requests per run\n via Pydantic AI `UsageLimits` (#183).\n\n### Changed\n- **Automations table gained Run as.** The unified automations table now shows\n (and filters by) which user's credentials each automation runs as.\n- **Run page polls less aggressively.** The run-detail auto-refresh now backs off\n (2s → 15s) instead of a fixed 1-second tick, so long runs don't trigger a full\n server re-render every second.\n\n### Fixed\n- **Sidebar \"Action needed\" failure card.** Uses the proper\n `sentiment-negative-subtle` surface (no more muddy brown in dark mode) and a red\n CTA instead of an orange-on-red clash.\n\n## [v2026.6.21] — Tasks Inbox + LinkedIn triage agent — shipped 2026-06-17\n\n### Added\n- **Tasks Inbox.** One workspace queue of everything your agents are waiting on\n you for, pinned to the top of the sidebar with a live count badge. Each item\n carries the agent's proposed action — you review, edit, and submit. Search,\n filters, sortable columns, friendly (non-JSON) context rendering, and success\n toasts on every action.\n- **Snooze.** Move an item out of the inbox for a set duration; it returns on its\n own — or sooner if a newer reply lands on the thread.\n- **Agents work the inbox too.** It's a tool surface over Native MCP and the\n `/api/v1/inbox` REST API (`produce_inbox_item`, `list_inbox_items` with\n search / filter / sort, plus claim / propose / complete) — humans and agents\n act on the same queue as peers.\n- **Action menus + one-click execution.** A producer can attach a set of typed\n options (a reply with an editable draft, or one-click actions), one marked\n recommended. The inbox renders them as buttons and *runs* the action on click\n (e.g. send or archive on the source system), not just records it.\n- **Self-learning loop.** What you change versus what the agent proposed is a\n signal. Agents in \"learning mode\" aggregate signals and open a single\n improvement PR per cycle, rather than one per correction.\n- **LinkedIn inbox-triage agent.** Pulls recent LinkedIn threads into the Tasks\n Inbox, drafts a reply from the full thread, and offers one-click **Send**,\n **Send + Archive**, or **Archive**. Keeps the queue capped at a few open\n threads (tops up, never piles on), skips threads you've archived / handled /\n snoozed, and pages back for fresh ones when the recent list is all handled.\n- **Manual-credential connections.** Connect services with no OAuth (e.g.\n LinkedIn) by pasting a few values alongside setup instructions, stored as\n workspace secrets. \"New connection\" is now a four-type picker — Native MCP /\n Composio / Manual credential / Secret.\n\n### Changed\n- **Automations is one full-width table.** Schedules, event triggers, and\n inbound webhooks now live in a single searchable / filterable table instead of\n a three-tab split. \"+ New Automation\" opens a type picker (Schedule / Event\n trigger / Webhook), mirroring New connection.\n- **Shared DataTable across every list.** Agents, runs, connections, inbox,\n automations, and the rest share one table component — consistent row hover,\n whole-row click, and sortable headers everywhere.\n- **Skills page restructured** into a table of installed skills with a top-right\n \"+ New Skill\" picker and a clickable per-skill detail view.\n\n### Fixed\n- **Inbox sidebar count updates the moment you act on an item** — the workspace\n layout is revalidated on submit / dismiss / execute / snooze.\n- **Runner:** import `AnthropicProvider` correctly when building Pydantic AI\n agents, and apply an explicit 300s read timeout on the Anthropic streaming\n client (#178).\n- **API:** use axum 0.8 path syntax for `/runs/{id}`.\n\n## [v2026.6.20] — Connections index polish, Skills detail, sidebar dismiss — shipped 2026-06-17\n\n### Changed\n- **Connections index is now searchable, filterable, and sortable.** The list\n reads like the agents/tools tables — a search box, a type filter, and\n sortable column headers (default A→Z by name) instead of a flat list.\n- **Connection detail/edit cleanup.** Every attribute moved into the detail\n table (the header is just the logo + name); all actions (Refresh / Reconnect /\n Edit / Disconnect) sit top-right as buttons styled like the agent view. Edit\n shows only when the connection is actually editable (secret, Composio, or DCR\n native MCP), and renaming is a direct field on the edit page rather than an\n expand-to-rename toggle.\n- **New connection is a two-step picker** — choose a provider / Composio /\n secret, then fill in just that option's form.\n- **Skills: clickable detail view.** Each installed skill links to a detail page\n showing its install source (linked), repo path, file count, and the full\n SKILL.md rendered as markdown, with Remove top-right.\n- **Sidebar \"Action needed\" prompts are dismissible.** A small Dismiss link next\n to Connect hides a connection prompt you don't intend to act on (per-user,\n persisted locally).\n\n### Fixed\n- **Self-key (Tembo) connections no longer flood the audit log.** The implicit\n Tembo Agent Studio connection is re-minted automatically; it no longer writes\n a \"Connection authorized\" event each time. Real OAuth authorizations are still\n audited.\n- **Create-agent prompt hides defunct/renamed native providers** so the Tembo\n Coding Agent isn't offered connections that no longer exist.\n- **CI lockfile.** Repaired a corrupted `web/pnpm-lock.yaml` (duplicate mapping\n keys) that broke `pnpm install --frozen-lockfile`.\n\n### Dependencies\n- Sweep of routine bumps: Next 16.2.9, axum 0.8.9, thiserror 2.0, shadcn 4.11,\n plus the Astro group, `@tailwindcss/postcss`, `eslint-config-next`, chrono,\n regex, uuid, `@types/node`, and `actions/checkout` v6.\n\n## [v2026.6.19] — Connections & Slack apps reworked into list / view / edit — shipped 2026-06-16\n\n### Changed\n- **Connections reworked into an agents-style list.** The tabbed Connections\n shell (Native MCP / Composio / Secrets + an admin sub-page) is now one list of\n every connection you have — native-MCP and Composio OAuth plus workspace\n secrets — each row tagged by type, with a **\"+ New connection\"** button and,\n for admins, **\"Manage providers\"** (provider enable/disable + bring-your-own\n OAuth apps moved to `/connections/providers`).\n - **New connection** is a two-step picker: choose an option (a provider,\n a Composio toolkit, or a secret), then fill in just that option's form.\n - Each connection gets a **detail view** (status, tools, token expiry, with\n Refresh / Reconnect / Disconnect) and an **edit** view (rename, or rotate a\n secret). OAuth flows land you on the new connection's detail page; old\n `/connections/{native-mcp,composio,secrets}` URLs redirect to the new shape.\n- **Slack apps moved to the Build menu, reworked into list / detail / edit.**\n Slack apps left Settings for **Build → Slack apps**: a list of apps (rows),\n a dedicated **New Slack app** view, a detail view with the setup checklist /\n request URLs / manifest / install, and an edit view for credentials. The\n install flow returns to the app's detail page.\n- **Tools: admins see the whole workspace's catalog.** A workspace admin now\n sees tools from every member's active connections on the Tools tab, not just\n their own — so they can see what agents across the workspace can reach.\n (API/MCP/agent surfaces stay per-user.)\n\n## [v2026.6.18] — Audit timeline detail + sign-in redirect for deep links — shipped 2026-06-16\n\n### Fixed\n- **Signed-out deep links now go to sign-in, not a 404.** A signed-out visitor\n following a deep link (e.g. `//audit`) hit a page that gates with\n `notFound()`, so they saw a 404 — which reads as a broken link, not \"please\n sign in\". An auth gate in the proxy (middleware) now redirects them to the\n sign-in landing with the intended path in `?next=`, and they return there once\n signed in. `/mcp` and `/for-agents` stay open (they authenticate with a bearer\n token, not a session).\n\n### Changed\n- **Audit timeline shows real detail for every event.** A full pass over the\n event log:\n - **Connections** show the provider (e.g. *Attio*, *Tembo Agent Studio*) and a\n stack tag (Native MCP / Composio), instead of a bare \"· default\" — native-MCP\n events store the provider slug, which the timeline now resolves to a display\n name.\n - **Every event kind has a human label and an inline summary** where it carries\n useful data (API keys, webhooks, native-MCP OAuth apps, provider toggles,\n secret connections, Slack apps/installs/messages, sign-ins with IP + browser,\n agent version promotions). Previously ~20 kinds rendered as raw strings like\n `api_key.created` with no detail.\n - **A per-row \"Details\" expander** reveals the full event payload for anything\n the summary doesn't surface.\n - **Member events record who invited.** Accepting an invite now records the\n original inviter (`invited by …`), which was previously lost once the invite\n was accepted.\n\n### Dependencies\n- **esbuild 0.28.1, vite 8.0.16, js-yaml 4.2.0, @babel/core 7.29.7.** Clears six\n Dependabot advisories across the two earlier rounds. All are dev/test/build\n tooling (never in the deployed runtime), and the vectors (Deno install path,\n Windows dev server, untrusted-YAML parsing the app doesn't do) don't apply to\n this stack — bumped to keep the security tab clean.\n\n## [v2026.6.17] — Audit coverage for the API/MCP surface, sign-ins, and membership — shipped 2026-06-16\n\n### Added\n- **Audit coverage for the public API & MCP surface.** Mutations made through\n the REST API (`/api/v1`) and MCP server (`/mcp`) — which shipped unaudited in\n v2026.6.16 — now write to the audit timeline, stamped with `via` (`api` or\n `mcp`) and the acting API key so a programmatic change is distinguishable from\n an in-app one and traceable to a key. Covers automation create/update/delete,\n Slack-app create/update/delete, and `send_slack_message` (destination + length\n only — never the message body). Runs and agent-change requests aren't\n double-logged — they already project into the timeline from their own tables.\n The in-app Slack-app management actions, which were also never audited, now\n record the same events.\n- **Sign-in audit events.** A successful login now writes an `auth.login` event\n (with IP address and user agent) to the timeline of each workspace the user\n belongs to, via a better-auth session hook.\n- **Membership & setup audit events.** New events for inviting a member\n (`member.invited`), revoking an invite (`member.invite_revoked`), a member\n joining (`member.added` — on both admin-add and invite-accept), connecting a\n repo (`repo.connected`, which stores a GitHub PAT), creating a workspace\n (`workspace.created`), and syncing agent guidance (`guidance.synced`).\n\n### Dependencies\n- **esbuild → 0.28.1.** Clears two Dependabot advisories\n ([GHSA-gv7w-rqvm-qjhr](https://github.com/advisories/GHSA-gv7w-rqvm-qjhr),\n [GHSA-g7r4-m6w7-qqqr](https://github.com/advisories/GHSA-g7r4-m6w7-qqqr)).\n esbuild is dev/test-only here (transitive via vitest/tsx/vite in `web` and the\n Astro toolchain in `docs`, never in the deployed runtime), and neither\n vector — the Deno install path and the Windows dev server — applies to this\n stack, but bumped to keep the security tab clean. `docs` needed a\n `pnpm.overrides` pin since `astro`/`vite 7` held esbuild at 0.27.x.\n\n## [v2026.6.16] — Public API & MCP server, sub-agent orchestration, prompt caching — shipped 2026-06-15\n\n### Added\n- **Public REST API + MCP server.** Drive a workspace programmatically — from\n Claude Code or any HTTP/MCP client. A new **personal API key** (Settings →\n API keys) authenticates both surfaces as you (your role, your per-user\n connections), is shown once, and can be disabled or revoked anytime.\n - **REST API** under `/api/v1`: list/read agents, validate a spec, list/read\n and trigger runs, browse the tool catalog and connection status, manage\n automations, manage Slack bots (create/update/delete, admin only), and hand\n authoring to the Tembo Coding Agent (`POST /api/v1/agent-changes`). See\n [REST API](./docs/src/content/docs/api.md).\n - **MCP server** at `/mcp` (Streamable HTTP): the same capabilities as MCP\n tools (`list_agents`, `get_agent`, `validate_agent_spec`, `list_runs`,\n `get_run`, `list_tools`, `list_connections`, `list_automations`,\n `list_slack_apps`, `trigger_run`, `create_automation`,\n `request_agent_change`, plus admin-only `create_slack_app` /\n `update_slack_app` / `delete_slack_app`). Connect with\n `claude mcp add --transport http tas https:///mcp --header \"Authorization: Bearer tas_…\"`.\n See [MCP server](./docs/src/content/docs/mcp.md).\n- **Admin Slack-app management over the API & MCP.** The slack-apps surface\n (previously read-only) now supports create/update/delete, gated at\n `workspace_admin` on both REST (`POST /api/v1/slack-apps`,\n `PATCH`/`DELETE /api/v1/slack-apps/{id}`) and MCP (`create_slack_app`,\n `update_slack_app`, `delete_slack_app`) — matching Settings → Slack apps.\n Creation writes metadata only (the app comes up `configuring` and isn't live\n until an admin completes the one-time browser OAuth install), so no secrets\n are needed to create one over the API.\n- **`send_slack_message` — real Slack DMs and channel posts.** Agents could only\n reach Slack via Composio, whose \"DM\" posts to the bot's own connected account\n (the human never sees it). A new `send_slack_message` MCP tool (operator-gated)\n + `POST /api/v1/slack-messages` use a workspace Slack app's bot token to DM a\n real person by `toEmail` (resolved to a real DM + notification) or post to a\n `channel`. So an agent on the `tembo-agent-studio` MCP can actually notify\n someone instead of self-DMing through Composio.\n- **Sub-agent orchestration with rolled-up cost.** When an agent calls the\n `tembo-agent-studio` MCP `trigger_run` from inside its own run (an orchestrator\n fanning work out to per-source sub-agents), the spawned run is now linked to its\n parent (`run.parent_run_id`). The parent's run page gets a **Sub-runs** section\n listing each child with its tokens + cost, a **Combined** total, a **Prompt\n cache** read/write breakdown, and a **Sub-agents use** row of the MCP logos the\n children actually invoked.\n- **Agents list: MCPs column + filter.** The agents inventory shows each agent's\n declared connection logos; for an orchestrator it also shows (dimmed) the MCPs\n its sub-agents bring in, derived from the `parent_run_id` graph. A **Filter by\n MCP** dropdown matches an agent on its own or its sub-agents' MCPs.\n- **Native-MCP tool reference for the Tembo Coding Agent (`/for-agents`).** When\n TAS asks CAP to author or edit an agent, the prompt now lists native-MCP\n connection slots (provider → authorized names) alongside Composio slots, and\n links each instance's own cached tool reference at `GET /for-agents/.md`\n so CAP can learn a native MCP's exact tool slugs. Auth is a signed, expiring,\n `(workspace, user)`-scoped bearer token that unlocks only the tool catalog —\n stateless, no DB key. Connection context is now shared across all three authoring\n call sites (new-agent form, API `request_agent_change`, in-app chat edit).\n- **Orchestration is the preferred multi-source pattern.** The Pydantic AgentSpec\n guide TAS syncs into every connected repo now steers CAP toward a thin\n orchestrator + focused sub-agents (driven through the `tembo-agent-studio` Native\n MCP: `list_connections` / `trigger_run` / `get_run`) instead of one agent holding\n every source's tools in one growing context — and to reuse an existing\n single-purpose sub-agent rather than duplicating it. The guidance version hash\n auto-bumps, so repos re-bootstrap the refreshed guide on their next request.\n- **Native MCP: Tembo Agent Studio (self-key) and Dialed.** Added a\n `tembo-agent-studio` self-key native-MCP provider (so an agent can drive its own\n TAS instance) and [Dialed](https://dialed.day) to the native-MCP catalog. Agents\n declare them with `connections: [{ type: …, source: native-mcp }]`.\n- **Anthropic prompt caching + cache-aware cost.** An agentic run re-sends the\n whole prompt every step, so the large static prefix (system instructions + tool\n schemas) was re-billed at full input rate on each of 10+ steps. The runner now\n caches the system prompt + tool definitions and rolls a breakpoint over the\n growing history (Anthropic models; a spec can override), billing the repeated\n prefix at the cache-read rate (~0.1×) after a one-time write surcharge (~1.25×) —\n roughly a 3–5× cost cut on tool-heavy runs. Cost accounting is now cache-aware,\n and the run-steps footer shows a `prompt cache: N read · M write` line when the\n cache engaged.\n- **Provider logos on native-MCP surfaces.** A shared `mcpLogoUrl(slug)` helper\n serves local art for providers Composio's logo CDN doesn't carry (Pylon, Dialed,\n Tembo Agent Studio) and the CDN for everything else. Logos now render on the run\n page, the agents-list MCPs column, the agent **Uses** row, and all three\n native-MCP card states on the Connections page (each keeping its generic-glyph\n fallback).\n\n### Changed\n- **Native-MCP slots fall back to your sole connection.** A spec that pins a\n provider by a slot name the user didn't use verbatim (e.g. `name: default` vs a\n connection named `tembo`) was rejected as not-connected. Now, when the named slot\n is absent but the user has exactly one active connection for that provider, TAS\n uses it — at both run time and in the pre-run check. Ambiguous (2+ slots, none\n matching) still requires naming one.\n- **Tool catalog hides orphaned tools.** `listToolsForUser` now surfaces a cached\n tool only when a matching active connection still exists, so tools from renamed,\n disconnected, or stale connections no longer linger (e.g. the duplicate listings\n after the `tembo` → `tembo-agent-studio` slug rename). Applies everywhere the\n catalog feeds: Tools tab, Connections, `/api/v1/tools`, MCP `list_tools`, and\n `/for-agents`.\n- **Native-MCP authorizations request `offline_access`.** Providers that only\n issue a refresh token when the OIDC `offline_access` scope is requested (e.g.\n Dialed) were going dark when their short-lived access token expired. TAS now\n appends `offline_access` at authorize time when the auth server supports the\n refresh-token grant (DCR providers only). Existing such connections must be\n reconnected once to obtain a refresh token.\n\n### Fixed\n- **Native-MCP token refresh for Dialed/Fathom.** The Rust refresh path validates\n a connection's origin against its own hardcoded allowlist, which lagged the web\n catalog — so every Dialed refresh aborted, the expired token was used, and the\n run 401'd. Added Dialed + Fathom to the allowlist and a vitest drift guard that\n fails CI if a future catalog provider isn't mirrored into the Rust allowlist.\n- **Defunct native-MCP connections can be cleaned up.** A connection to a provider\n that left the catalog (e.g. the old `tembo` self-key connection after the rename)\n lingered as an orphaned row that couldn't be disconnected and kept its minted\n `tas_` key alive. The Connections → Native MCP page now shows a \"removed provider\"\n banner with a one-click Remove that deletes the rows, revokes the self-key, and\n drops the cached tools.\n- **Sidebar stopped nagging \"Connect\" under the single-connection fallback.** The\n sidebar's \"Action needed\" list reimplemented the missing-connection check with a\n strict slot-name match and lacked the native single-connection fallback, so it\n flagged a connected agent as needing attention. Both the sidebar and the run-\n blocking pre-flight now route through shared helpers so they can't drift again.\n- **YOLO creates show a pending card immediately.** A YOLO (direct-commit) create\n is optimistically marked committed the moment CAP accepts it, but the agents page\n re-filtered pending creates to only submitted/PR-opened ones — so a YOLO create\n showed nothing until Tembo finished building it. The page filter now keeps\n direct+committed creates too, matching the query.\n\n### Migrations\n- `0049` (per-user, workspace-bound API keys) and `0050` (`run.parent_run_id` for\n sub-run linking) apply on the next Rust api restart.\n\n## [v2026.6.15] — Fathom MCP, free-text agent names — shipped 2026-06-09\n\n### Added\n- **Run input on the run view.** A run started with an optional message now shows\n that text as an **Input** field (under Trigger) on the run detail page.\n- **Fathom Native MCP.** Added [Fathom](https://fathom.video) (meeting\n notes/transcripts) as a native MCP provider — connect it from Connections with\n TAS-managed OAuth (Fathom supports dynamic client registration + PKCE, so\n there's no per-customer OAuth-app setup). Agents reach it with\n `connections: [{ type: fathom, source: native-mcp }]`.\n- **Free-text agent names.** Name an agent in normal text (e.g. \"Inbox Triage\")\n — the create form slugifies it for the filename and saves the text as a new\n optional `title:` field on the spec. The agents list, agent page, and chat\n header show the `title` (falling back to the slug); the slug `name` stays the\n stable identifier for URLs, runs, and automations, so nothing else changes.\n\n### Fixed\n- **Run-now dropped the optional message.** The \"Run now\" dialog's submit button\n was a Radix `AlertDialogAction`, which dismissed (unmounted) the dialog the\n instant it was clicked — racing the form submission and sending the agent an\n empty `user_message` (so it behaved as if no input was given). Now a plain\n submit button: success redirects, errors keep the dialog open with the input.\n- **Historical run-cost backfill.** Recomputed the stored `cost_usd` on existing\n runs against the corrected model rates (Opus $5/$25; gpt-5.x priced per\n variant), so the Runs list and dashboard totals match the run-detail estimates\n for pre-fix runs. Only rows with token counts + a known model family are\n touched; unknown models and already-correct families are left as-is.\n *(migration 0048)*\n\n## [v2026.6.14] — Agent Skills, YOLO mode, Claude Fable 5 — shipped 2026-06-09\n\n### Added\n- **Agent Skills.** A workspace **Skills** area to install reusable Agent Skills\n (Anthropic's `SKILL.md` folders) into your repo under `skills/`, from three\n sources: the [skills.sh](https://www.skills.sh/) directory (by slug / GitHub\n URL), a custom `.zip` upload, or **imported from the Claude Skills API** (the\n org's custom skills + Anthropic's pre-built ones, via the version-content\n export). An agent opts in with a `skills:` field; at run time the named skill\n folders are mounted via pydantic-ai-skills so the model can load their\n instructions and run their scripts — **locally, with any model** (no Anthropic\n code-execution sandbox). Install/remove is workspace-admin and audited.\n- **YOLO (direct-commit) delivery mode.** A per-workspace setting\n (**Settings → Tembo Coding Agent → Improvements delivery**) chooses how the\n coding agent's changes land: **Always PR** (default — a reviewable pull\n request) or **YOLO**, which commits straight to the default branch with no PR.\n The mode is read per request to shape the Tembo prompt, so toggling takes\n effect on the next submission with no repo re-sync. YOLO improvements show a\n terminal **Committed** status and link the landed commit; a best-effort scan\n finds the marker commit on the default branch to attach it. Switching mode is\n workspace-admin-only and audited. *(migration 0047 — `workspace.commit_mode`\n + `improvement.delivery` / `commit_sha` / `commit_url`)*\n - YOLO requires the default branch to accept direct pushes from the coding\n agent; if it's protected behind required pull requests, keep Always PR.\n- **Claude Fable 5 support.** Agents can use `anthropic:claude-fable-5` —\n Anthropic's most capable widely-released model (Mythos-class, 1M context),\n GA on the Claude API as of 2026-06-09. Priced in the run-cost estimates at\n $10/$50 per MTok (web + API tables), and added to the authoring guidance as\n the top-capability step-up above Opus 4.8.\n\n### Fixed\n- **Opus run-cost estimates.** Corrected the `claude-opus` rate from the stale\n $15/$75 to the current $5/$25 per MTok (current Opus 4.5–4.8), so cost\n estimates and the stored `cost_usd` are accurate. (The $15/$75 rate only ever\n applied to the deprecated Opus 4.1/4.0.)\n- **OpenAI gpt-5.x run-cost estimates.** The single `gpt-5` rate ($1.25/$10) was\n mis-pricing the whole gpt-5.x family. Added per-model rates for the current\n flagships and intermediate releases — gpt-5.5 ($5/$30), gpt-5.4 ($2.50/$15,\n + mini/nano), gpt-5.2 ($0.875/$7), gpt-5.1 ($0.625/$5) — ahead of the bare\n `gpt-5` catch-all. gpt-4o / gpt-4.1 / o3 were already correct. Authoring\n guidance now references `openai:gpt-5.5` instead of the older gpt-5.2.\n\n## [v2026.6.13] — In-app docs, workspace rename, Automations area — shipped 2026-06-09\n\n### Added\n- **In-app documentation.** The product manual now ships inside the app, pinned\n to the exact version you're running — a **Docs** link in the sidebar opens a\n full viewer with search, a sticky collapsible nav whose open/closed state\n persists across sessions, and a GitHub-stars link in the footer. Content is\n organized by audience — **For Operators** (The Basics / Advanced), **For\n Admins** (workspace admin + self-hosting), and **For Instance Admins** — and\n every page, including the live **Changelog** and **Roadmap**, is bundled at\n build time so it always matches the deployed release.\n- **Rename a workspace.** A new **Settings → General** section (workspace-admin\n only, now the default Settings tab) renames a workspace. GitHub-org style: the\n URL slug follows the name, and the previous slug is kept alive as a redirect —\n preserving deep links (`/old/agents/x` → `/new/agents/x`) — so existing links\n and bookmarks never break. Renames are recorded in the audit log. *(migration\n 0046 `workspace_slug_alias`)*\n- **Workspace-level Automations area.** A dedicated **Automations** section in the\n sidebar with its own nav — **Schedules**, **Triggers**, and **Webhooks** — so\n recurring runs and event wiring have a home across the whole workspace, not\n just per-agent. On the agent page, Schedules moved to the top of the renamed\n **Automation** tab.\n- **Role badge in the shell.** Your workspace role (Workspace Admin / Operator /\n Viewer) now shows under your name in the bottom-left user menu.\n- **Agents table filters.** Filter the agents inventory by label and by model.\n\n### Changed\n- **Roadmap rewritten** as a simple, unphased list of ideas — each described in a\n couple of sentences and linked to a GitHub Discussion holding a draft **TASIP**\n (Tembo Agent Studio Improvement Proposal) where you can weigh in.\n- **Docs stay in sync by policy.** `AGENTS.md` now instructs coding agents to\n update the docs alongside feature changes, backed by a non-blocking CI reminder\n when app code changes without a matching docs change.\n\n### Fixed\n- **Reliable merged-PR detection for improvements.** Improvements with a known PR\n number are now confirmed via a direct PR fetch instead of the search API, so a\n merged improvement no longer lingers as \"open\".\n\n## [v2026.6.12] — Live run timeline, output discipline, Native MCP admin — shipped 2026-06-08\n\n### Added\n- **Run view rebuilt as a live step timeline.** The run-detail page now shows\n one view — built live and identical when finished — of what the agent did,\n step by step: the model's narration (revealed word-by-word while running), the\n tools it called (provider logo + ok/failed/running badge inline), and a\n per-step **In / Out token + cost** readout, with a totals footer (In, Out, and\n combined total). A \"Copy\" button lifts the whole transcript (narration +\n answer + tool calls) as plain text. The final answer is the last step — no\n separate Output box.\n - The wrapper streams text deltas + tool-call/result events as they happen; the\n runner persists `run_step` / `run_tool_call` rows live so the table builds in\n place, reconciled authoritatively at run end.\n - Per-step token usage + per-tool-call attribution. *(migrations 0043\n `run_step`, 0044 `run.streamed_output`, 0045 `run_step.summary`)*\n- **Output discipline for every agent.** A global instruction makes agents work\n silently — no step-narrating or raw tool-output dumps in the reply — while\n allowing one short \"what I'm doing\" line per tool step (which feeds the\n timeline narration). Stops agents from burning the output-token budget.\n- **Real parallel-tool-call limiter.** Agents now default to\n `model_settings.parallel_tool_calls = False` — an API-level cap so the model\n issues one tool call at a time instead of fanning out parallel bursts that get\n providers (e.g. Attio) rate-limited. Opt back in per-agent via the spec. Paired\n with tool-use guidance to back off on `retry after` errors.\n- **Native MCP admin screen.** A workspace-admin \"Manage providers\" screen\n (Connections → Native MCP) to enable/disable which providers members see and\n register **multiple named OAuth-app instances** per confidential provider, so a\n second connection can use a second app. *(migration 0042\n `workspace_native_mcp_provider` + instance columns on\n `workspace_native_oauth_client`)*\n\n### Changed\n- **Agents table:** Name is the first column with alphabetical default sort;\n Labels get their own column; the Framework column is gone; the Model column\n strips the provider prefix (`anthropic:claude-sonnet-4-6` → `sonnet-4-6`).\n- **Per-agent Runs tab** reuses the workspace Runs table (same columns minus\n Agent + Input), keeping status/trigger/search filters.\n- **Sidebar \"Action needed\"** collapses duplicate missing-connection alerts into\n one card (\"HubSpot for 3 agents\") instead of one per agent.\n- **Dashboard:** dropped the \"Workspace-wide activity\" subhead; Recent runs now\n show who triggered each run.\n\n### Migrations\n- `0042_native_mcp_admin` — provider enable flags + OAuth-app instances.\n- `0043_run_step` — per model-step token usage + `run_tool_call.step_ordinal`.\n- `0044_run_streamed_output` — live partial output column.\n- `0045_run_step_summary` — per-step narration text.\n\n## [v2026.6.11] — HubSpot via Native MCP (bring-your-own OAuth app) — shipped 2026-06-08\n\n### Added\n- **HubSpot as a Native MCP provider** (`https://mcp.hubspot.com`). HubSpot\n doesn't support auto-registration (DCR) and uses a confidential OAuth client,\n so this adds a **\"bring-your-own OAuth app\"** mode to Native MCP — generic for\n any future non-DCR provider:\n - `McpProvider.authMode` (`dcr` | `manual`); manual providers run a\n confidential PKCE flow with an admin-stored client_id/secret instead of\n self-registering a public client.\n - An admin **Configure OAuth app** card on **Connections → Native MCP** shows\n the redirect URI to register and stores the client_id/secret (encrypted);\n the per-user **Connect** button is gated until it's configured.\n - Token refresh presents the confidential client_secret for these\n connections. *(migration 0041 `workspace_native_oauth_client`)*\n\n To use it: create a HubSpot MCP auth app with redirect URI\n `/api/connections/native/hubspot/callback`, paste its client_id/secret\n under Connections → Native MCP, then Connect and reference\n `{ type: hubspot, source: native-mcp }` in an agent.\n\n### Changed\n- **Automations** collapses by default on the agent Automation tab (matching\n Triggers + External webhooks), with a count in the title.\n\n### Migrations\n- `0041_workspace_native_oauth_client` (per-workspace BYO OAuth client for manual\n Native MCP providers). Applied on api boot.\n\n## [v2026.6.10] — Agent view redesign + run-time connection guard — shipped 2026-06-08\n\nThe agent page was a long vertical stack; it's now a focused, Settings-style\nview with a left side-nav. Plus a guard that stops a run before it starts when\nthe connections aren't set up. Web-only — no new migrations.\n\n### Added\n- **Agent view side-nav** — the agent page is reorganized into a shared header\n (name, version, owner, connections, primary actions) + a left tab rail, with\n one real route per tab: **Overview** (30-day dashboard + recent runs),\n **Runs**, **Automation** (triggers + webhooks + schedules), **Versions**,\n **Definition** (spec + tools module), **Activity** (audit timeline), and\n **Settings**. Each tab fetches only its own data.\n- **Connection icons on the agent view** — a row of the external services the\n agent uses, each with its **provider name + logo** (logos borrowed from\n Composio's library; a generic icon when a slug has none).\n\n### Changed\n- **Decluttered the agent header** — Delete moved to **Settings → Danger**;\n **Promote to Stable** moved to the **Versions** tab (the header keeps the\n read-only \"Stable vN\" badge); the ownership picker moved to **Settings** (the\n header shows a read-only owner). The header's action row is just\n **View source · Chat to edit · Run now**.\n- **Triggers + External webhooks collapse by default** on the agent view, with a\n count in the title so configured items stay visible.\n\n### Fixed\n- **Block a run when the acting user's connections aren't set up** — a clear\n pre-flight message (\"You haven't connected: HubSpot. Authorize under\n Connections, then run again.\") instead of a pydantic-ai traceback mid-run.\n Applies to Run-now and Chat-to-edit.\n- **Lint/CI** — pin `eslint` to 9 (eslint 10 removed an API `eslint-plugin-react`\n still uses, crashing the lint step), and fix the placeholder Dependabot config\n (real per-ecosystem groups; Astro + Starlight always bump together).\n\n### Dependencies\n- A wave of Dependabot updates: Next 16.2.7, React 19.2.x, Astro 6.4.4,\n TypeScript 6, and many GitHub Actions (`checkout`, `setup-node`, the docker/*\n actions, codeql, pages) — all verified green.\n\n## [v2026.6.9] — Agent lifecycle, tool observability, and the ETL-agent stack — shipped 2026-06-08\n\nA big release. Agents gain a real **version lifecycle** (draft → stable) and\n**tool-call observability**, and a new **ETL-agent stack** lands: agents can run\ndeterministic **Python tools**, authenticate them through a new **Secrets**\nsubstrate, and be **triggered by external webhooks** (Clay first). The full\n**user manual** is now published, and the `guides/` directory moved into it.\n\n### Added\n- **Agent versioning & lifecycle** — agents now have a **draft** (the live repo\n file) and a promotable **stable** snapshot frozen in Postgres. Promotion\n records owner + version; runs default to **stable** for predictability (chat\n iterates on draft). The agent page shows version history, the draft↔stable\n diff, and a change summary. *(migration 0037)*\n- **Sidecar Python tools** — a Pydantic agent can declare `tools_module: foo.py`,\n a sibling file of deterministic functions the model calls as tools (transforms,\n scoring, ETL) at **no token cost**. Schemas derive from each function's\n signature + docstring; calls are captured like MCP tools. Extra deps go in\n `api/scripts/requirements-tools.txt`.\n- **Secrets — the 3rd connection substrate** — free-form, per-workspace API keys\n (e.g. Clay) set under **Connections → Secrets** (admin-managed, AES-256-GCM).\n Sidecar tools read a value via `tas_tools.secret(\"\")`; injected only\n into runs that have a tools module. *(migration 0039)*\n- **External webhook triggers** — a per-agent inbound endpoint\n (`/api/hooks/webhook/`) fires a run from any outside system. Built for\n Clay's model: `POST` JSON + an `Authorization: Bearer ` header\n (constant-time verified, shown once, rotatable); fire-and-forget 202. The\n request body reaches the agent as a `{trigger_type, webhook, payload}`\n envelope. *(migration 0040)*\n- **Tool-usage tracking** — every tool an agent calls is captured per run\n (success + failure), rolled up per agent over 30 days, and surfaced in a\n workspace-wide, filterable **Tool uses** view. *(migration 0038)*\n- **Pylon** as a Native MCP provider.\n- **Two-level collapsible sidebar** navigation (Build / Activity / Integrations /\n Workspace).\n- **Published user manual** — an Astro Starlight site at\n , deployed from `docs/` on every change.\n\n### Changed\n- **Prefer Native MCP over Composio** in the agent-authoring guidance, with a\n dynamic provider list; default model guidance moved to `claude-opus-4-8`, and\n the `labels:` extension field is documented.\n- **`guides/` merged into the docs site** and deleted; the README and deploy\n guides now point at the published manual.\n\n### Fixed\n- **Native MCP token refresh** for short-lived tokens (Pylon ~5-min tokens) via a\n per-provider refresh allowlist.\n- **Composio**: surface connect errors instead of swallowing them; support\n bring-your-own-auth toolkits; flag unknown toolkit slugs; fix a Pylon→Linear\n OAuth misroute and a \"no active connection\" false negative.\n- **Agent versioning**: fix a promote crash (`FOR UPDATE` with an aggregate) and\n owner-picker name disambiguation.\n- **\"Improve the Agent\"** now surfaces a thrown/stale server action (\"refresh —\n a new version shipped\") instead of failing silently.\n- **Docs build**: upgrade Starlight to 0.39 for Astro 6 compatibility, and\n replace the placeholder Dependabot config with real per-ecosystem groups\n (Astro + Starlight always bump together).\n\n### Migrations\n- `0037_agent_version`, `0038_run_tool_call`, `0039_workspace_secret_connection`,\n `0040_workspace_webhook`. The api applies them on boot.\n\n## [v2026.6.8] — Slack apps: launch agents from Slack — shipped 2026-06-04\n\nTAS can now host per-team Slack bots that launch a **label-scoped subset** of\nyour agents — separating cheap routing from right-sized execution, so dozens of\nagents are reachable from Slack without dozens of channels or one expensive\nmega-agent.\n\n### Added\n- **TAS-managed Slack apps** (Settings → Slack apps, admin-only) — register one\n bot per team (e.g. a sales bot and a support bot), each scoped to a subset of\n agents by label. Coached setup: copy a prefilled Slack manifest, paste\n credentials, then **Add to Slack** (OAuth) to install. Signing secret, client\n secret, and bot token are AES-256-GCM encrypted; multi-app from day one.\n- **Launch agents from Slack** — slash command `/tas `,\n `@mentions`, and DMs. The run acts as the Slack user (matched by email),\n falling back to the app's default owner, and the result posts back in-thread.\n- **Agent labels** — add `labels: [sales]` to an agent spec to group it in the\n inventory and scope which Slack app may launch it. Documented as a TAS\n extension field in [`AGENT_FORMAT.md`](./context/shipped/0.1/AGENT_FORMAT.md).\n- **Natural-language routing** — a Slack message that doesn't name an agent is\n routed by a cheap Haiku 4.5 classifier to the best-fit scoped agent (or replies\n with the menu when nothing fits).\n- **Agent picker modal + App Home directory** — `/tas` with no agent opens a\n picker; the bot's Home tab lists every agent it can launch.\n- **\"Run agent on this message\" shortcut** — launch an agent with any Slack\n message as its input, prefilled into the picker.\n- **Runs \"Source\" column** — the runs list now shows how each run was instigated\n (Manual / Scheduled / Event / Slack), who it acted as, and — for Slack — a deep\n link back to the originating conversation.\n- **Dashboard \"Slack (30d)\" column** — per-member count of Slack-launched runs,\n with a per-bot breakdown on hover.\n\n### Changed\n- Slack replies render the agent's Markdown as Slack **mrkdwn** (bold, headings,\n links, bullets, tables) and drop the leading `user>` transcript echo.\n- Dashboard **Team** rows append the email when two members share a first name.\n\n### Hardening\n- Per-Slack-user rate limit, replay dedupe on Slack retries, and an audit event\n (`slack.dispatch`) per Slack-launched run.\n\n### Fixed\n- Slack Web API calls are now form-encoded — fixing the read methods that\n silently ignore a JSON body, so the acting-user email→member mapping and the\n message permalinks (the \"View in Slack\" links) work.\n\n## [v2026.6.7] — Team visibility + admin management — shipped 2026-06-04\n\nA batch focused on workspace admins seeing and managing what members own.\n\n### Added\n- **Team section on the dashboard** — a per-member table (Connections /\n Automations / 30-day runs), sorted by run activity. Hover a count for the\n underlying list (which toolkits are connected, which agents have\n automations) via a styled, fast tooltip.\n- **Member detail view** — admins click a member (from Settings → Members or\n the Team table) to see their tool connections, the automations that \"Run as\"\n them, and their recent runs. Useful before offboarding (see #64).\n- **Admins can view + rename any member's connections** — a \"Viewing\" dropdown\n on the Connections page (defaults to self). When viewing another member you\n can Rename and Refresh; Connect/Reconnect/Disconnect are hidden since OAuth\n must be performed by that member.\n- **Admin \"Run as\" in the manual Run-now dialog** — pick which member to run as;\n the run uses that member's connections (same model as an automation owner).\n- **\"Run as\" owner column** on the automations list.\n\n### Changed\n- Member rows: **Remove** is red with a confirm step, and the whole row links to\n the member detail view.\n- The Composio connection-rename action is now gated to owner-or-admin (parity\n with the native-MCP rename).\n\n## [v2026.6.6] — Dismiss pending agents + settings polish — shipped 2026-06-04\n\n### Added\n- **Dismiss pending agents** from the workspace home. In-flight chat-to-PR\n creates can now be removed from the inventory via an inline confirm\n (operator+); it stops tracking the create here and leaves the GitHub PR\n alone (the PR / Tembo-session links still reach it).\n\n### Fixed\n- **Composio webhook secret field** no longer implies a `whsec_` prefix — those\n secrets are prefix-less hex, so the masked preview/placeholder were\n misleading (same class of fix as the Tembo API key field in v2026.6.5).\n- **Sidebar \"Action needed\" CTA** (the \"add an LLM key\" prompt) now updates\n without a manual browser refresh when a provider key is added or removed — it\n lives in the workspace layout, which now revalidates at layout level.\n\n## [v2026.6.5] — Tembo authoring fix + favicon fixes — shipped 2026-06-03\n\n### Fixed\n- **Tembo Coding Agent authoring (the \"Invalid token\" 401).** Requests now hit\n `POST /public-api/task/create`, where the workspace's Tembo API key\n authenticates as `Authorization: Bearer`. We were calling the bare\n `/task/create` path, which a different internal auth gate rejected with\n \"Unauthorized - Invalid token\" — so new-agent / chat-to-edit / Improve failed\n even with a valid key. **This is the fix that unblocks authoring.**\n- **Workspace favicon blank in production.** The favicon route's redirect used\n the container's internal address (`https://0.0.0.0:8080/…`) behind the proxy,\n which the browser can't reach; it now emits a relative `Location`. Also\n cache-busts the default and per-workspace favicon URLs so a stale per-origin\n favicon entry clears (and switching a workspace's favicon actually updates).\n- **Tembo API key field** no longer shows a misleading `tembo_` prefix in the\n masked preview/placeholder — keys are prefix-less.\n\n### Added\n- **Actionable Tembo auth errors.** A rejected/rotated key now surfaces \"Tembo\n rejected the API key — update it under Settings → Tembo Coding Agent\" instead\n of a raw 401, across the new-agent / chat / Improve flows.\n- **Setup guide:** the agents repo must also be authorized in Tembo (Settings →\n Integrations → Source Control) for the coding agent to open PRs.\n\n### Changed\n- Sidebar agents icon matched to Tembo's (#61).\n- Docs: clarified CalVer is year.month + a per-month release counter (not the\n day of the month).\n\n## [v2026.6.4] — Workspace deletion, invite auto-join, LLM-key CTA — shipped 2026-06-03\n\n### Fixed\n- **Invited existing users now join automatically.** Inviting someone who\n already had an account previously left a pending invite with no way to accept\n it — on sign-in they were prompted to create their own workspace instead of\n landing in the one they were invited to. Existing users are now added to the\n workspace at invite time, and any already-pending invite resolves on the\n user's next sign-in. (Recommended upgrade for instances using invitations.)\n\n### Added\n- **Delete a workspace** — Settings → **Danger** tab, with a type-to-confirm\n step, gated to workspace admins. Removes all workspace data (members, runs,\n schedules, connections, secrets, settings, audit, invitations); the GitHub\n repository and its agent files are not touched.\n- **Sidebar CTA when no LLM provider key is set** — a workspace with neither an\n Anthropic nor OpenAI key now shows an \"Action needed\" card linking to\n Settings → LLM Providers, since agents can't run without one.\n\n## [v2026.6.3] — Security hardening, dashboard runs, version surfacing — shipped 2026-06-03\n\nA security-focused release (several authorization/tenant-isolation fixes), plus\ndashboard and CI improvements. **Recommended upgrade for all instances.**\n\n### Fixed (security)\n- **Reject an insecure placeholder `BETTER_AUTH_SECRET` at runtime** — the app\n now refuses to start with the dev placeholder secret, so a misconfigured\n deploy can't run with a guessable session-signing key (#52).\n- **Tenant scoping on the run-detail endpoint** — `get_run` now enforces the\n caller's workspace, preventing cross-workspace run reads (#58).\n- **Authorization check on repo connect** — `connectRepoAction` was missing a\n role check; added it so only authorized members can connect a repo (#55).\n- **Mass-assignment fix** — `owner_user_id` can no longer be set from request\n input (#56).\n- **SSRF + token exfiltration fix** — closed a server-side request forgery /\n token-leak path (#57).\n\n### Added\n- **Settings → Version tab** — shows the running release (release builds link to\n their GitHub release; edge/CD builds link to the commit).\n- **Recent runs on the dashboard** — the latest runs workspace-wide, above\n Improvements, with fully clickable rows linking to the run.\n\n### Changed\n- **CI checks gate + tests on PRs.** A `checks` workflow now runs on every PR:\n web typecheck + vitest + eslint (now blocking after the lint cleanup in #54),\n and api `cargo fmt --check` + clippy + `cargo test`. A separate pipeline\n continuously deploys `main` to Tembo's internal instance behind that gate.\n- **Docs:** Railway guide documents pinning explicit version tags for\n production vs. `:latest` for throwaway instances.\n\n## [v2026.6.2] — Reproducible runtime, setup guide, Microsoft sign-in fix — shipped 2026-06-02\n\nA small maintenance release: lock the last floating runtime dependency so a\nrebuilt image tag is reproducible, ship a start-here setup guide, and fix\nMicrosoft Entra sign-in for self-hosted instances.\n\n### Fixed\n- **Microsoft Entra sign-in.** Entra commonly omits the `email` claim from both\n the id_token and the userinfo endpoint (the address lives in\n `preferred_username`/`upn`), which made better-auth fail sign-in with\n `email_is_missing`. The Microsoft provider now decodes the id_token and\n derives the email from `email ?? preferred_username ?? upn`.\n- **Opaque sign-in errors.** Failed OAuth callbacks redirected back with a bare\n `?error=` and no UI feedback; the sign-in page now renders an actionable\n message (invite-only, missing email, token exchange, …) and surfaces the raw\n code for support.\n\n### Changed\n- **Pinned `composio==0.13.1`** in the api runtime image. It was the one\n unpinned Python dep (pydantic-ai and pyyaml were already pinned); since\n Composio ships frequently, an unpinned bump could break connection-using\n agents on the next rebuild of a given image tag.\n\n### Added\n- **Version on the login screen.** The footer now reads \"powered by Tembo Agent\n Studio ``\" so operators can see at a glance which release an instance\n is running. The version is **baked into the image at build time** (web\n Dockerfile `TAS_VERSION` build-arg), so it always matches the running image —\n no env var to set or keep in sync per instance.\n- **`guides/CUSTOMER_SETUP.md`** — a zero-to-running checklist covering\n everything a new customer must procure and do: infra, auth provider, LLM\n keys, secrets, deploy env, first-run instance-admin bootstrap, per-workspace\n setup, and creating the first agent. Linked from the README as the\n start-here guide.\n\n## [v2026.5.31] — Container image publishing — shipped 2026-05-31\n\nMakes TAS deployable from prebuilt images instead of a source build, and\nhardens the supply chain around them.\n\n### Added\n- **Container images published to GHCR.** A release workflow\n (`.github/workflows/release.yml`) builds and pushes `tas-api` +\n `tas-web` to `ghcr.io/tembo/` on every `v*` tag, tagged\n `` / `.` / `latest`. Images are **cosign**\n keyless-signed and carry SBOM + provenance attestations; **Trivy**\n scans each image (report-only). A `compose.release.yaml` runs the\n stack from those images (`docker compose -f compose.release.yaml pull\n && up -d`), pinned by `TAS_VERSION` and kept in lockstep with each\n release via an auto-opened PR. Customers no longer compile Rust/Node\n on their host.\n- **Onboarding sign-out link.** A \"Signed in as … Not you? Sign out\"\n affordance on both onboarding steps (`/onboarding` and\n `/onboarding/repo`) so someone who authenticated with the wrong\n Google account can recover without an app shell to hang a user menu\n off of.\n- **Dependabot** enabled for GitHub Actions + npm.\n- **Instance-admin role + root `/settings`.** Deployment-level admin via\n the `INSTANCE_ADMIN_EMAILS` allowlist, and a root `/settings` surface\n (instance-admin only) with an editable, DB-backed instance name\n (`instance_settings`, migration 0031; env fallback).\n- **Invite-only instance + workspace invitations.** Account creation is\n rejected unless the email is an instance admin or has a pending invite.\n Workspace admins invite by email (migration 0032) and get a copy-paste\n template; invitees auto-join their workspace(s) on first sign-in.\n Workspace creation is instance-admin-only. `INSTANCE_ADMIN_EMAILS` is\n the required bootstrap env (without it nobody can sign in to a fresh\n instance).\n- **Build fix:** `api/build.rs` (`rerun-if-changed=migrations`) so new\n migrations actually embed in the image — `sqlx::migrate!` is\n compile-time, and a migration-only change otherwise got cached out.\n\n### Changed\n- **api image runs as a non-root user** (uid 1001), matching web. The\n run path writes nothing to disk (spec via stdin, result via stdout),\n so no writable app dir is needed.\n- **api defaults to a dual-stack bind** (`API_BIND_ADDR=[::]:8080`).\n Serves IPv4 + IPv6, so Docker Compose is unchanged while IPv6-only\n private networks (e.g. Railway service-to-service) reach the api with\n no configuration.\n\n### Fixed\n- **Client auth base URL is resolved at runtime** from the browser\n origin instead of the build-time `NEXT_PUBLIC_BETTER_AUTH_URL` (which\n is inlined when the image is built, so a prebuilt GHCR image baked\n `http://localhost:3000` and sign-in failed on any real domain). Fixes\n sign-in for every image-based deploy.\n- **postcss bumped to ≥ 8.5.10** via a pnpm override to clear\n GHSA-qx2v-qp2m-jg93 (a CSS-stringify XSS in the copy Next pins\n transitively). Not reachable in TAS — build-time, dev-authored CSS —\n resolved to clear the alert and de-dupe to one postcss.\n\n## [v2026.5.29] — First CalVer release — shipped 2026-05-29\n\nThe cutover to date-based releases. Everything through Phase 0.4\n(Governance depth) is captured below; this tag marks the first release\ncut from `main` under the new scheme and ships one new capability on top\nof v0.4.\n\n### Added\n- **Native-MCP OAuth token auto-refresh.** The runner now refreshes\n expiring native-MCP access tokens *before* a run reads them, instead\n of letting an expired token reach the agent and 401 mid-run. For any\n active oauth2 native connection (e.g. Attio) whose `token_expires_at`\n is at/near expiry, it spends the stored `refresh_token` (granted via\n `offline_access`) for a fresh token at the provider's discovered token\n endpoint, re-encrypts the credentials, and bumps `token_expires_at`.\n A rejected refresh (dead refresh token) proactively flips the\n connection to `stale` so the UI prompts Reconnect; transient failures\n are logged and the run proceeds on the existing token. Best-effort and\n per-connection. `crypto.rs` gained an `encrypt()` twin to its existing\n `decrypt()`; refresh lives in the runtime (`native_oauth.rs`) so no\n plaintext round-trips through the web container.\n\n### Changed\n- **Roadmap tracking moved to GitHub Issues.** Phase 0.5 / 0.6 user\n stories and the backlog are now issues (label `enhancement`; 0.5 and 0.6\n milestones, backlog = no milestone). The `context/*/USER_STORIES.md`\n docs are redirect pointers to the issues and retain design rationale +\n out-of-scope notes.\n- **Version files adopt CalVer.** `api/Cargo.toml` and\n `web/package.json` move from the long-stale `0.1.0` to `2026.5.29`.\n\n## [v0.4] — Governance depth — shipped May 2026\n\n### Added\n- **Native MCP connections.** Second connection substrate alongside\n Composio: TAS-managed OAuth straight to the provider's official\n MCP server. The user clicks Connect and TAS performs MCP-spec\n discovery + Dynamic Client Registration (RFC 7591) + PKCE under\n the hood — no per-provider OAuth-app setup, no `build.attio.com`\n side quest. `lib/mcp-providers.ts` is a one-line-per-provider\n catalog (today: Attio); everything else (auth URL, token URL,\n scopes, DCR endpoint) is read from `/.well-known/oauth-protected-\n resource`. Agent spec `connections:` entries dispatch by\n `source:` (`composio` default, `native-mcp` opt-in); the Python\n wrapper builds one `MCPToolset` per declared (provider, name)\n slot with the user's bearer token in `Authorization` headers and\n honors `tools:` narrowing on native entries via\n `FilteredToolset`. Rust runner decrypts the `workspace_connection`\n row per acting user and ships the credentials as\n `TAS_NATIVE_MCP_CONNECTIONS` env.\n- **Unified tool catalog + Tools tab.** Normalized\n `workspace_mcp_tool` table (migrations 0029 + 0030) caches every\n tool exposed by any connection, indexed by source + provider +\n connection name. Primed on connect, refreshable from a per-row\n button on the Connections page, cleared on disconnect. New\n workspace-level `//tools` page lists everything in a\n searchable, filterable table with click-to-copy slugs — kills\n the \"is it `RUN_BASIC_REPORT` or `run-basic-report`?\" guessing\n game that the kebab-case-vs-UPPER_SNAKE_CASE split between\n Attio's MCP and Composio's REST wrappers used to force on you.\n- **Lean CAP prompt + canonical agent guidance.** Tembo Coding\n Agent prompts dropped ~16KB by replacing the inline canonical-\n guidance block with a pointer at the on-disk files (Sync agent\n guidance pushes the canonical content to the customer repo on\n demand; a scheduled refresh lives in\n `context/backlog/`). `PYDANTIC_GUIDE` learned both connection\n substrates, the slug-case gotcha, and a Switching-from-Composio-\n to-Native-MCP recipe.\n- **Test foundation (Vitest + Polly.js + Playwright/Cucumber).**\n `pnpm test` runs unit + integration in ~300ms covering the RBAC\n policy + the workspace-authorize funnel (the v0.4-02 deny-test\n exit-bar item — operator is denied workspace_admin actions,\n no-session short-circuits before workspace lookup so existence\n isn't leaked). `pnpm test:bdd` drives a real Chromium through\n Gherkin-style feature files via Cucumber.js — pilots: anon\n redirects to sign-in, signed-in workspace_admin lands on the\n dashboard (seeded via direct Postgres write + HMAC-signed\n session cookie). HTTP fixtures recorded as Polly.js cassettes.\n- **Immutable audit changelog (US-0.4-01).** Append-only\n `audit_event` table records actor / when / source / target /\n payload for the event types that don't already live in another\n table (secret rotations, connection authorize/disconnect/rename,\n automation lifecycle, trigger lifecycle, agent delete/restore,\n repo disconnect). The unified timeline reads explicit writes\n UNION'd with derived projections of `run` + `improvement` (both\n already event-shaped), so v0.3 emitters needed zero\n re-instrumentation. Workspace-wide `//audit` page\n with source / actor / agent / time-window filters (URL-driven,\n deep-linkable). Per-agent Timeline section on the agent detail\n page with click-through to the full history. New `Audit`\n sidenav item.\n- **Audit JSON export (US-0.4-04).** \"Export JSON →\" affordance\n on the audit page (honors current filter set) and the per-agent\n Timeline (scoped to that agent). Envelope carries the filter\n snapshot + truncated flag alongside the rows. Export is itself\n audited (`kind=audit.exported`). Capped at 10,000 rows per\n download — streaming to a SIEM is the v0.5 open question per\n the story carve-out.\n- **RBAC (US-0.4-02).** Three workspace-scoped roles —\n workspace_admin, operator, viewer — with a strict hierarchy.\n `lib/rbac.ts` + `lib/auth-server.ts` centralize the policy\n layer; every mutating server action and OAuth route now\n funnels through `authorizeWorkspace(slug, minRole)` and\n returns DENIED_MESSAGE on insufficient role. Role assignments\n are themselves audited (`source=policy_change`,\n `kind=member.added | member.role_changed | member.removed`).\n New Settings → Members section with role picker, add-by-email,\n and remove affordances (workspace_admin only); last-admin\n demotion is blocked in the DB helper. UI affordance hiding\n (New agent, Run now, Delete agent, Chat-to-edit) keys off the\n current user's role; server enforcement remains the contract.\n Org-admin tier deferred until there are concrete cross-workspace\n endpoints to gate on it.\n- **RBAC-half of US-0.4-05 closed.** Role-assignment audit events\n (`member.added` / `member.role_changed` / `member.removed`) now\n carry the target user's name + email in the payload, and the\n audit UI renders them as readable rows (\"Alice · viewer →\n operator\" rather than the raw uuid). The audit-export event\n (`audit.exported`) renders the filter snapshot + row count.\n The policy-half of the AC (template version diffs, override\n events with justification) stays open until the policy\n substrate ships, since those event types don't exist yet.\n\n### Scope moves\n- **API-level deny test in CI → v0.4+.** The v0.4-02 AC asks for\n CI-verified API enforcement. Vitest deny-tests on the\n `authorizeWorkspace` funnel land in v0.4 itself\n (`web/src/lib/auth-server.test.ts`); the GitHub Actions workflow\n that would run them on every PR is in\n [`context/backlog/`](./context/backlog/USER_STORIES.md) — the\n enforcement is locked in by code + test, CI is the missing\n enforcement of the test.\n- **US-0.4-03 (org-level policy templates) → Backlog.** Needs an\n org concept (a scope above workspace) plus a generic policy\n resolver substrate; the rest of v0.4 ships cleanly without it.\n Pulls forward when a concrete customer use case lands or when\n v0.5 prep needs the substrate.\n- **New `context/backlog/` folder.** Sibling to the numbered\n phase folders; holds designed-but-unscheduled stories with\n `Moved from: vX.Y` provenance lines. Replaces the per-phase\n `Stretch (Considered, Deferred)` pattern as the home for\n stories that *don't* have a phase yet.\n- **`context/shipped/` folder.** Shipped phase folders (0.1, 0.2,\n 0.3) moved under `context/shipped/` so active phases stay\n uncluttered at the `context/` root. Docs themselves remain\n load-bearing references; only the directory layer changed.\n All cross-phase relative links updated; v0.4 → shipped uses\n `../shipped/0.X/`, shipped → v0.4+ uses `../../0.X/`, and\n sibling refs within `shipped/` stay as `../0.X/`. Root README +\n ROADMAP + a couple of source-file comments updated to point at\n the new paths.\n\n## [v0.3] — Operational surface — shipped May 2026\n\nThe day-two surface. Agents reach external services through a real\nsubstrate (no more \"the model knows how to write Slack messages but\nthe runtime can't actually call Slack\"). Operators get one screen\nper agent that answers \"how's it going?\" and \"if it's not, what's\nbroken?\" — the v0.3 phase's \"one screen, not four hours of log\nspelunking\" goal. The originally-planned rich-HITL pieces moved\nout to make room for Connections, which ate the phase honestly.\n\n### Added\n- **Composio-backed Connections substrate.** External services\n (Slack, Gmail, Google Sheets, Notion, GitHub, Linear, HubSpot,\n Salesforce, … ~1,043 in Composio's catalog) for agents to call\n at run time. Authorized once per user per workspace via\n Composio's hosted OAuth, cached as a `workspace_composio_connection`\n row keyed by `(workspace_id, user_id, toolkit_slug, name)`.\n Per-user model: each member authorizes their own toolkits;\n scheduled runs use the automation's \"Run as\" owner. The\n workspace Composio API key is itself a workspace secret\n alongside Tembo / Anthropic / OpenAI keys.\n- **Connections page (new top-level sidenav item).** Lists each\n `(toolkit, name)` slot declared by agents in the connected\n repo plus anything pre-authorized. Inline Disconnect /\n Reconnect / Rename actions per row, with toolkit logos pulled\n from Composio's catalog. \"Add another connection\" form sits at\n the bottom for pre-authorizing a slot before an agent declares\n it.\n- **Toolkit picker.** Combobox over Composio's full catalog,\n alphabetized, filter-as-you-type, name + slug side-by-side\n per row with the toolkit's logo. Catalog cached in-process for\n 1 hour.\n- **Named connection slots.** Agent spec's `connections:` accepts\n `{ name, tools }` per toolkit so the same user can hold\n multiple Gmails / Slacks / GitHubs and an agent can target a\n specific one. Canonical form is named slot + narrow tools list\n (turns on Composio's DIRECT_TOOLS preset, ~10× cheaper input\n tokens than the loose search-and-execute path).\n- **Pydantic-AI runtime pipe for Composio tools.** Python wrapper\n (`api/scripts/run_pydantic.py`) materializes a Composio session\n from the spec's `connections:` field, attaches it as an MCP\n toolset, and resolves each `(toolkit, name)` slot to the acting\n user's authorized connection. Imperative preamble prepended to\n the agent's instructions so tool-using models execute instead\n of hedging.\n- **Per-agent operational dashboard.** Health header (colored by\n 30-day failure-rate band), four stat tiles (Runs / Success rate\n / Spend / Avg duration), daily-trend bar (30-day strip with\n success / failure overlay), recent-failures grouping (top-5\n error prefixes by count, with a link to one example run each).\n Empty-history agents skip the dashboard so \"0\" tiles don't\n read as broken.\n- **Persisted run cost.** New `run.cost_usd` column populated at\n `mark_succeeded` time using a model-pricing table mirrored\n in Rust (`api/src/pricing.rs`). Cost column on the workspace\n Runs page renders with the same bar-chart background as\n Duration, scaled to the highest cost in view.\n- **Sidebar action-needed alerts.** When a repo agent declares a\n `connections:` slot the current user hasn't authorized, the\n sidebar shows \"Connect {toolkit} for {agent}\" with a direct\n authorize link. Per-user so each member sees their own gaps.\n- **Multi-workspace support.** Sidebar workspace switcher,\n multi-workspace onboarding, `/` redirect lands on the\n last-visited workspace (via `workspace_member.last_visited_at`).\n- **Automation \"Run as\" owner.** Scheduled runs use the\n automation's `owner_user_id` (defaults to creator). Owner\n picker in the automation form lists workspace members so the\n per-user connections model has a sensible answer for\n scheduled credentials.\n- **GitHub fetch cache.** `listDirectory` + `readFile` cached\n for 60s tagged per repo via Next.js fetch tags. Writes\n (`createFile` / `updateFile` / `deleteFile`) bust the tag via\n `updateTag`. Cuts the sidebar-driven scan cost.\n- **Event triggers (Composio-backed).** New `workspace_trigger`\n table binds a Composio trigger instance to an agent + owning\n user + connection slot. Per-workspace webhook endpoint at\n `/api/hooks/composio/{slug}` HMAC-verifies the inbound payload\n (`composio_webhook_secret` stored alongside the API key),\n resolves the trigger row, and enqueues a run with\n `trigger='event'`. Per-agent Triggers section on the detail\n page renders the list + a create form that takes a Composio\n trigger slug, a connection, and a JSON config. Event-driven\n runs show a purple **Event** badge on the workspace Runs page\n and the run-detail header.\n- **Agent inventory.** Workspace landing page is now a sortable\n table (Status / Name / Framework / Model / Runs 30d / Success\n / Last run) instead of a card grid. Facet pills filter by\n Active / Idle / Error / Pending / Invalid with live counts;\n free-text search across name. Pending creates + invalid agent\n files render inline as their own rows.\n- **Workspace dashboard.** `//dashboard` now mirrors\n the per-agent dashboard shape: health header banded by 30d\n failure rate, four stat tiles (Runs / Success rate / Spend /\n Avg duration), 30-day daily-trend bar, and a \"Top failing\n agents (30d)\" rollup with click-through to the latest failing\n run. Improvements counts + recent list stay below as\n secondary context.\n- **Log explorer (on `/runs`).** Search predicate extended to\n ILIKE across `error_message` in addition to user_message +\n output. Failed rows surface a two-line error excerpt inline\n so triage scans don't require a click. `/runs` now reads\n `status` / `trigger` / `agent` / `q` from URL search params\n so deep links land prefiltered.\n- **Failure-aware sidebar alerts.** \"Action needed\" rail now\n surfaces agents with at least one failure in the last 24h\n (\"Agent X failed N× in 24h → Open\") above the missing-\n connection alerts. Capped at five so a broken workspace\n can't shove the rail off-screen.\n- **Failure investigation links on run detail.** Failed-run\n detail page now offers two jumps: \"Find similar runs →\"\n (deep-links into `/runs` filtered to the agent + status=failed\n + error-prefix search) and \"View {agent} failure groups →\"\n (anchored deep link into the per-agent dashboard's grouped\n failures section).\n\n### Changed\n- **Create-agent prompt slimmed and rebuilt around Connections.**\n `buildCreateAgentPrompt` drops the verbose guidance-refresh\n block, points Tembo at the in-repo `AGENT_GUIDE.md`, tells it\n the canonical `connections:` form is named slot + narrow tools,\n and recommends defaulting to `anthropic:claude-opus-4-7` for\n tool-using agents (Opus executes; lower-tier models hedge on\n multi-step tool dances), with downgrade-to-Sonnet documented\n as the cost-optimization step once an agent is reliable.\n- **All `useActionState` forms switched to controlled inputs.**\n React 19's useActionState resets uncontrolled fields after\n each submission, including the returned-error path. Onboarding /\n repo-connect / secret-key / new-agent / run-now / automation /\n rename-connection forms all updated so a validation bounce\n doesn't wipe the user's typed input.\n- **Empty-input run default.** The Python wrapper used to\n substitute `\"Hello.\"` when a run had no user message — models\n greeted back instead of executing. New default is a directive\n (`\"Execute the job described in your instructions.\"`).\n- **Sticky sidebar.** Workspace nav stays put while the main\n column scrolls.\n- **Toolkit allowlist removed.** Earlier in the phase, TAS\n hardcoded the set of Composio toolkits it recognized. That was\n actively blocking Tembo from declaring legitimate connections\n (e.g. an email-reading agent that wanted `gmail`). Connections\n are now declared by agents, and any Composio slug is accepted.\n\n### Fixed\n- **Delete-agent UI lag.** Action redirects with `?deleted={name}`;\n the agents grid defensively filters that name from the\n rendered list AND shows a confirmation banner. Instant\n feedback even when the GitHub fetch cache hasn't propagated.\n- **Workspace secret validation accepted junk.** A literal HTML\n 404 page text once landed in a workspace's Composio API key\n field. Per-kind prefix sniff at save now catches this (`ak_`\n for Composio, `sk-` for OpenAI, `sk-ant-` for Anthropic);\n the runtime no longer 401s silently when a non-key string\n was pasted.\n\n### Scope moves\n- **HITL pause/resume + rich forms → v0.4.** Originally a v0.3\n anchor; the Connections substrate ate the phase, and the\n remaining v0.3 work (workspace-wide triage surfaces + failure\n investigation) landed in its place. HITL is the next major\n substrate piece and anchors v0.4.\n- **Workspace-wide triage surfaces → mostly shipped, residuals\n to v0.4.** Agent inventory ✓, workspace dashboard ✓, log\n explorer (extended `/runs`) ✓, failure-aware sidebar ✓.\n Topology map + tasks inbox land in v0.4 (tasks inbox depends\n on HITL anyway).\n- **Event-trigger form polish → v0.3+.** Trigger slugs are\n currently entered as free text (linked to Composio's catalog).\n Schema-driven per-trigger config forms (pulled from\n `getTriggerType`'s `config` schema) land in a later iteration.\n\n## [v0.2] — Authoring velocity — shipped May 2026\n\nThe chat-to-PR loop. A non-engineer describes an agent (or a change to one)\nin plain English; Tembo opens a pull request; the team reviews a diff.\n\n### Added\n- **Chat-to-create.** New agents start from a chat description on the\n `/agents/new` page. Tembo writes a valid agent file in the chosen\n framework's canonical shape and opens a PR. Pending creates appear as\n dashed-border cards on the agents grid until the PR merges.\n- **Chat-to-edit.** Each agent has a chat thread. \"Send to agent\" runs the\n agent with your message; \"Submit change request\" packages the message and\n hands it to Tembo, which opens a PR. Both intents share one composer.\n- **Improvement loop.** Run-detail \"Improve the Agent\" form ships free-text\n feedback to Tembo as a coding task. The opened PR carries a marker that\n lets TAS correlate merged PRs back to the improvement row. New\n `/improvements` page lists every submission with status (submitted /\n PR opened / merged / closed).\n- **Automations.** Scheduled runs via cron expressions. New `/automations`\n route with a list, create/edit form (live cron preview + next-fire in\n local time), and an enable/disable toggle. Agent detail page surfaces an\n agent's automations. Run rows show a \"Scheduled\" badge and link back to\n the automation. Single-process Node.js scheduler tick at 30s resolution,\n fires through the same `/internal/runs` path as manual runs.\n- **Runs page.** Workspace-wide run list with status / trigger / agent\n filters, ILIKE search across input + output, cursor-paginated \"Load\n more\". Whole-row click navigates to the run detail. Relative-time\n \"5m ago\" inside 24h, absolute `LocalTime` beyond. Subtle bar-chart\n background on the Duration cell scaled to the longest run in view.\n- **Dashboard.** Per-workspace landing page: active vs. all-time agent and\n run counts, weekly improvement breakdown, recent improvements feed.\n- **Run-now with input.** Clicking Run now on the agent detail page opens\n a dialog with an autofocused textarea for the user message. Empty\n submission preserves the prior \"no input\" behavior.\n- **Floating copy button** on the run-detail output card. Hover-only,\n cross-fades in over 150ms, strips the `[stop_reason]` suffix before\n copying.\n- **OpenAI provider.** Agents can declare `openai:gpt-...` models alongside\n Anthropic.\n- **AGENTS.md hierarchy.** A root `AGENTS.md` and `api/AGENTS.md` join the\n existing `web/AGENTS.md`. Each coding-request prompt to Tembo also pushes\n current TAS-managed guidance files into the customer's workspace repo:\n root `AGENTS.md`, `agents/AGENTS.md`, and per-framework `AGENT_GUIDE.md`\n files are refreshed on drift; customer-managed\n `ADDITIONAL_AGENT_INSTRUCTIONS.md` is created once, never overwritten.\n- **Settings → Sync agent guidance.** One-click bootstrap or refresh of\n the guidance files into the connected workspace repo, for repos whose\n agents predate the auto-bootstrap.\n- **LocalTime hover-to-UTC.** Datetime renders local with the local-tz\n abbreviation by default; hover/focus cross-fades to the same instant\n in UTC over 500ms. Uses inline-grid so the container sizes to the\n wider string and surrounding text doesn't jump.\n\n### Changed\n- **Passthrough runner.** Both supported frameworks now shell out to the\n upstream tool — Cargo AI via the bundled `cargo-ai` CLI; Pydantic AgentSpec\n via the real `pydantic-ai` library in a bundled Python venv. The Rust API\n no longer hand-rolls provider calls.\n- **Markdown output.** Agent output renders as markdown by default.\n- **Feedback → Improvement rename** everywhere (DB table, routes, UI copy).\n The PR-correlation marker `TAS-Feedback-ID:` is kept as a wire-format\n constant for back-compat with in-flight PRs.\n- **`/agents/new` simplified.** Removed \"From template\" and \"Paste\n definition\" tabs; chat is the only path now. Lib code for the removed\n paths (`createAgentFromTemplate`, `createAgentFromContent`,\n `commitAgentFile`, starter renderers) dropped.\n- **Base UI primitives.** New `Select` component built on `@base-ui/react`.\n `Badge` padding bumped, `Input` height bumped, framework label shortened\n to \"Pydantic\" / \"Cargo AI\".\n\n### Scope moves\n- **US-0.2-08 (event-driven triggers) → v0.3 US-15.** Depends on the\n Connections substrate v0.3 owns; building a one-off github-only\n webhook receiver in v0.2 would have been a snowflake.\n- **US-0.2-06 (HITL pause/resume) → v0.3 US-13b.** Merges cleanly with\n v0.3's rich-HITL-forms work; splitting it across phases meant v0.3\n would have to immediately rewrite the v0.2 surface.\n- **US-0.2-03/04 (PR policy) → backlog.** Blocked on the Tembo Coding\n Agent Platform shipping a direct-commit mode; today CAP always opens\n a PR, so there's no auto-merge surface to wire.\n\n## [v0.1] — Foundation — shipped May 2026\n\nThe trustworthy floor: self-hosted deploy, identity, repo connection, runs.\n\n### Added\n- Docker-compose deploy: Next.js 16 web + Rust axum API + Postgres.\n- Auth via better-auth + Google OAuth (email/password disabled, in-app\n instructions for swapping providers).\n- GitHub OAuth repo connection — token stored AES-256-GCM-encrypted on the\n workspace row.\n- Agents listed from the connected repo as a 3-column card grid (last run\n status, framework + model badges, search). Two framework families\n supported: **Pydantic AgentSpec** and **Cargo AI**, each under their own\n `agents//` subfolder.\n- Create-agent flow (from template or paste, with framework picker).\n- Manual runs against Anthropic Claude (Opus / Sonnet / Haiku). Output\n streams to a run detail page with status, model, queued/started/duration,\n and token consumption + approximate cost.\n- Soft-delete + restore for agents (commits to the repo on both ends;\n deletion record retained for audit).\n- Per-workspace favicon picker (default set + custom upload).\n- Theme picker in settings: System / Light / Dark mode toggle, eight\n built-in presets (Light, Paper, Pure Light, Dark, Midnight, Forest,\n Ember, Blackout), local-only persistence." }, "connections": { "title": "Connections",