-
Notifications
You must be signed in to change notification settings - Fork 0
fix(skills): correct tool-surface drift in build/integrations/agenda skills #10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,6 @@ | ||
| --- | ||
| name: brains-build | ||
| description: The catalog of higher-level brains features beyond search — boards, board skills, dataset recipes, dashboards, pages, automations, workflows, mini-sites, the Telegram bot, and the overnight digest. Use when the user wants to track a list, build a tracker/CRM, automate a recurring task, coordinate a goal with a team, publish a deck/one-pager, or asks "what can brains do." Names the right feature and the flow tool to start it. | ||
| description: The catalog of higher-level brains features beyond search — boards, board skills, dataset recipes, dashboards, pages, automations, workflows, mini-sites, board forms, the Telegram bot, and the daily digest. Use when the user wants to track a list, build a tracker/CRM, automate a recurring task, coordinate a goal with a team, publish a deck/one-pager, or asks "what can brains do." Names the right feature and the flow tool to start it. | ||
| --- | ||
|
|
||
| # brains feature catalog | ||
|
|
@@ -13,15 +13,16 @@ tools carry it. | |
| | Feature | What it is | Reach for it when… | Start with | | ||
| |---|---|---|---| | ||
| | **Board** | Spreadsheet-like dataset on a brain; rows are JSON, shared & queryable | "track a list of…", "keep a table/CRM/pipeline of…", "log every X" | `create_board_flow` | | ||
| | **Board skill** | Named saved LLM action over a board's rows | "every row, do X", "summarize/score/enrich each row", repeated lookup | `create_board_skill` | | ||
| | **Board skill** | Named saved LLM action over a board's rows | "every row, do X", "summarize/score/enrich each row", repeated lookup | `create_board_skill`; run a saved one with `run_board_skill` | | ||
| | **Automation** (feed board) | An automation that fetches from email/cal/drive on a cron and appends rows | "run this nightly and feed a board", "keep this list fresh from email/cal/drive" | `create_automation_flow` | | ||
| | **Dashboard** | Live HTML view over a board (stats / charts / table / kanban / tabs …) | "make me a dashboard", "show this as cards/kanban/chart", "change the dashboard" | `get_dashboard` → follow the returned `skill` → `set_dashboard` (`engine_version: "v2"`) | | ||
| | **Page** | First-class note in a brain | "save this as a note", "keep this writeup findable" | `create_page` | | ||
| | **Automation** | Sandboxed TS program on a cron schedule with a scoped token | "every morning do X", "auto-draft Y when Z", anything re-prompted on a timer | `create_automation_flow` | | ||
| | **Workflow** | Goal container: charter + KPIs + deadlines + roster + owned board + paused template automations; one status flip pauses/un-pauses all | "ship X by Q3", "coordinate this initiative with a team & deadline" | `create_workflow_flow` | | ||
| | **Mini-site** | Static sandboxed HTML on a brain — deck, one-pager, dashboard | "build me a deck/one-pager", "render this board visually", "share a link" | `create_mini_site` | | ||
| | **Board form** | Chat-with-agent intake page that appends a row to a board dataset on submit | "collect responses", "give people a form/signup link" | `create_board_form` (then `list_board_forms` / `update_board_form` / `list_board_form_responses` / `delete_board_form`) | | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡 |
||
| | **Telegram bot** | The brain over Telegram | "text it from my phone", "ping me without the laptop" | (point to the bot) | | ||
| | **Overnight digest** | Auto daily/weekly read on what's coming up | "morning brief", "what should I be thinking about" | `get_overnight_digest` | | ||
| | **Daily digest** | Not a tool — a recipe-installed automation that writes a "Daily digests" board + dashboard | "morning brief", "what should I be thinking about" | `install_recipe slug="starter-pack-my-day"` (browse with `list_recipes`) | | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡 |
||
|
|
||
| ## Picking among the three that overlap | ||
|
|
||
|
|
@@ -33,6 +34,18 @@ tools carry it. | |
| goal-shape is present.) | ||
|
|
||
| Always use the **`*_flow`** tool for create/setup/scaffold asks — using | ||
| `create_board` / `create_automation` / `create_workflow` directly skips the | ||
| `create_board` / `save_automation_draft` / `create_workflow` directly skips the | ||
| playbook and yields a structure that doesn't fit. Use the bare tools only when | ||
| reproducing an existing entity verbatim or when the playbook tells you to. | ||
| (`update_automation` edits an existing automation in place — that one is fine | ||
| without a flow.) | ||
|
|
||
| ## Once it exists — the tools around a board | ||
|
|
||
| | Need | Tools | | ||
| |---|---| | ||
| | **Share it** | `share_board` / `share_mini_site` / `share_folder` — `scope:'user'` (default, one email) or `scope:'org'` (whole workspace, needs `confirm:true`). Name a reusable audience once with `create_share_circle`. | | ||
| | **Per-dataset access** | `enable_board_dataset_acl` flips one board to deny-by-default (irreversible, owner-only), then `grant_board_dataset_access` / `revoke_board_dataset_access` / `list_board_dataset_access`; `set_board_dataset_subject` marks the column that identifies a row's subject. | | ||
| | **Files & external data** | `upload_board_file` attaches a file (`get_board_file_url` for the link); `create_board_link` binds the board to an adapter-backed external resource (http_json / ics / github / monday). | | ||
| | **Undo a bad edit** | Dashboards, mini-sites and board column-schemas are versioned: `list_history` → `get_history_entry` → `revert` (entity: `dashboard` \| `mini_site` \| `board_schema`). The revert is itself snapshotted, so it's reversible too — say so before anyone panics. | | ||
| | **Automation credentials** | `automation_secret_set` / `automation_secret_get` / `automation_secret_list` / `automation_secret_delete` — never inline an API key into automation code. | | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,6 @@ | ||
| --- | ||
| name: brains-integrations | ||
| description: Managing which integrations the user has — listing what's connected (Gmail, Calendar, Drive, Monday, GitHub, …), and installing / upgrading / uninstalling them via codex recipes and the starter-pack bundle. Use when the user asks "what's connected", "can brains read from X", or wants to set up / add / update / remove an integration. | ||
| description: Managing which integrations the user has — listing what's connected (Gmail, Calendar, Drive, Monday, GitHub, …), and installing / upgrading / uninstalling them via codex recipes and the starter-pack bundle. Also covers authoring: publishing your own recipe to the catalog and managing it as a publisher. Use when the user asks "what's connected", "can brains read from X", wants to set up / add / update / remove an integration, or wants to build / publish a recipe of their own. | ||
| --- | ||
|
|
||
| # Integration lifecycle | ||
|
|
@@ -24,23 +24,32 @@ bounce the user to the browser for the common case: | |
| slugs: `gmail-inbox`, `gcalendar`, `gdrive-files`, `github-issues`, | ||
| `monday-items`. Idempotent — re-calling for an already-installed recipe | ||
| returns the existing install. | ||
| - **Web UI — browse catalog:** for "what's available?" send the user to | ||
| `/recipes` (integrations, boards, automations, workflows, bundles). There's | ||
| no MCP tool to enumerate the catalog, so the web UI is the way to discover | ||
| slugs the user doesn't already know. | ||
| - **Browse the catalog over MCP:** `list_recipes` enumerates installable | ||
| recipes — `tier` is `'catalog'` (curated, default), `'yours'` (the caller's | ||
| own), or `'community'` (other users' published ones), with optional | ||
| `kind` / `category` / `q` filters. Use it to discover slugs the user doesn't | ||
| already know; `recommend_recipes` picks a few with an evidenced reason when | ||
| the user has no specific target in mind. `/recipes` in the web UI is the same | ||
| catalog with pictures. | ||
| - **Web UI — starter pack:** for "set me up" / "install the basics", send the | ||
| user to `/recipes/starter-pack` — one click bootstraps the three Google | ||
| integrations (gmail-inbox, gcalendar, gdrive-files) atomically. Bundle | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡 "Bundle cascades only run through the web UI" is stale in the same way as the drift this branch fixes: |
||
| cascades only run through the web UI. | ||
|
|
||
| ## Upgrade | ||
|
|
||
| Upgrades run through the web UI (there is no MCP upgrade tool). Each | ||
| integration page (`/integrations/<install_id>`) shows a "Newer version | ||
| available" banner when an upgrade exists. If the install came via the | ||
| starter-pack bundle (`source_bundle_slug` is set), the Upgrade button | ||
| redirects to upgrading the **bundle** — don't upgrade bundle-sourced | ||
| integrations in isolation. | ||
| Read version drift from here: `list_installed_versions` returns one row per | ||
| install (`slug`, `name`, `kind`, `version`, `state`) — the caller's *actual* | ||
| pinned versions, so you never have to guess which My Day / starter-pack they're | ||
| on. Compare against the catalog's current version from `list_recipes`. | ||
|
|
||
| The upgrade itself still runs through the web UI — there's no MCP upgrade tool. | ||
| `install_recipe` is idempotent and dedups rather than re-pinning an existing | ||
| install, so it is not an upgrade path. Each integration page | ||
| (`/integrations/<install_id>`) shows a "Newer version available" banner when an | ||
| upgrade exists. If the install came via the starter-pack bundle | ||
| (`source_bundle_slug` is set), the Upgrade button redirects to upgrading the | ||
| **bundle** — don't upgrade bundle-sourced integrations in isolation. | ||
|
|
||
| ## Uninstall / manage | ||
|
|
||
|
|
@@ -50,8 +59,47 @@ user's secrets for that install), `pause_integration` / `resume_integration` | |
| installs with state + cost), and `get_integration_status` (one install's | ||
| health). Get the `install_id` from `list_my_integrations`. | ||
|
|
||
| The web UI also exposes Uninstall on each entity page with a 7-day recovery | ||
| window; from `/recipes/<slug>` it cascades to every entity whose | ||
| `source_recipe_slug` matches (and for a bundle, every child). Use | ||
| Tune an install without reinstalling it: `set_integration_config` (installer-side | ||
| config, e.g. which repos github-issues ingests), `set_integration_overrides` | ||
| (tighten per-run / per-month limits — you can only lower the recipe's caps), | ||
| and `run_integration_once` for an on-demand test run instead of waiting for | ||
| cron. Publishers can flip state across every install of a recipe they own with | ||
| `bulk_set_integration_state`. | ||
|
|
||
| The whole-recipe cascade is callable over MCP too: `preview_uninstall_recipe | ||
| slug=<slug> brain_id=<uuid>` shows the blast radius (entities stamped with the | ||
| slug plus deps that would be orphaned) without mutating anything, then | ||
| `uninstall_recipe` does it in one transaction — or pass `entity_id` to drop a | ||
| single entity. Always preview first for a bundle. The web UI exposes the same | ||
| thing per entity page. Everything lands in a 7-day recovery window; use | ||
| `list_uninstalled` when the user asks "what did I just uninstall" before they | ||
| click Recover. | ||
|
|
||
| ## Authoring a recipe (plugin-only) | ||
|
|
||
| These tools are `pluginOnly` — they exist on this surface and nowhere else, so | ||
| if the user wants to *publish* something, this is the only place it can happen. | ||
|
|
||
| - **Start with the playbook, not a blank template.** To author an integration | ||
| recipe, call **`create_integration_flow`** first — it returns the full | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Checked this against the tree rather than the PR description — the dependency is already satisfied, so no gate or caveat is needed. ssvlabs/brains#871 merged 2026-07-20T15:06Z, and it has since been promoted past Adding an inline "unavailable until #871" note now would be actively wrong, so I've left the authoring section as-is. While I was in here I re-verified the rest of the branch the same way — extracted every backticked identifier from the three changed SKILL.md files and diffed it against the real tool surface built from That sweep did turn up one real gap, now fixed in |
||
| IntegrationTemplate shape (auth, trigger, source, outputs, allowed_origins, | ||
| tool_grants, …) as a playbook to follow. Do NOT hand-roll a template or guess | ||
| at its fields; the spec lives in the playbook, not here. | ||
| - **Publish:** `publish_recipe` (kind-agnostic — board / automation / workflow / | ||
| bundle / integration) or `publish_integration_recipe` (integration-specific). | ||
| Both validate the template server-side and write nothing if it's invalid. | ||
| `unpublish_recipe` / `unpublish_integration_recipe` pull a recipe from the | ||
| catalog (existing installs are untouched — uninstall those separately). | ||
| - **Versioning is append-only.** A brand-new slug publishes at v1; re-publishing | ||
| a slug you own auto-increments to `max(version)+1`, the old version stays as a | ||
| historical row, and existing installs keep their pinned version. There is no | ||
| in-place edit — fix a mistake by publishing the next version. | ||
| - **`private` defaults to TRUE** for a new recipe: it's visible and installable | ||
| only by the author until it's published with `private: false`. Say this out | ||
| loud after publishing, or the user will wonder why nobody can see it. A | ||
| version bump inherits current visibility unless `private` is passed. | ||
| - **Manage what you publish:** `list_publisher_recipes` (your recipes + install | ||
| counts by state), `get_publisher_recipe` (one recipe's detail — auth, limits, | ||
| recent install errors, publisher-secret *names*), and the publisher vault via | ||
| `list_publisher_secrets` / `rotate_publisher_secret` / `delete_publisher_secret`. | ||
| You cannot publish under a slug someone else owns. | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🟡
get_boardgives no ordering guarantee and takes no sort argument; it defaults tooffset: 0,limit: 100. "take the newest row" therefore reads a stale row once thedailydataset passes 100 rows, which it will — the My Day recipe appends one per day. Page to the end viaoffsetusing the returnedpage.total, or passfilteron the dataset's date field for the window.