diff --git a/.agents/skills/create-squad/SKILL.md b/.agents/skills/create-squad/SKILL.md new file mode 100644 index 0000000..d2d8618 --- /dev/null +++ b/.agents/skills/create-squad/SKILL.md @@ -0,0 +1,151 @@ +--- +name: create-squad +description: Author a new Agent Squad bundle — scaffold it from the template, interview the author, fill every file, and validate. Use when the user wants to create, build, or add a new squad (a deployable bundle of proactive Pancake sub-agents). +--- + +# Create a squad + +Author a complete, valid Agent Squad bundle with the user. Work through the steps in order +— later steps depend on earlier ones. + +## Step 1 — Load the contract + +Before writing anything, read, in this order: + +1. [`docs/bundle-reference.md`](../../../docs/bundle-reference.md) — the exact file contract. +2. [`docs/creating-a-squad.md`](../../../docs/creating-a-squad.md) — the public-grade + authoring guide and principles. +3. The skeleton bundle [`template/`](../../../template/) — every file. Your output mirrors + its structure. + +Do not invent the contract from memory — read these files. + +## Step 2 — Interview the author + +Ask the user what they want, and don't scaffold until you have answers for all of it: + +- **The squad** — its purpose, and a kebab-case `name` (globally unique, ≤ 64 chars). +- **Each agent** — `id` (kebab-case), role / `description`, `model` (`haiku`/`sonnet`/`opus`, + string enum), `heartbeat` — a curated subset of [OpenClaw's + `agents.list[].heartbeat`](https://docs.openclaw.ai/gateway/config-agents#agents-defaults-heartbeat). + Only six sub-fields are accepted: `every`, `model`, `lightContext`, + `isolatedSession`, `skipWhenBusy`, `timeoutSeconds`. `every` is an OpenClaw duration + string in units `ms`/`s`/`m`/`h` (e.g. `"30m"`, `"2h"`, `"24h"`, `"0m"` to disable); + named values like `"daily"` are invalid. `heartbeat.model` is the same `haiku`/`sonnet`/`opus` + enum. Keep each agent single-lane and focused. +- **Skills** — which are squad-wide (every agent gets them) vs agent-specific. +- **Required identities** — external sites the squad needs connected, each with a reason. +- **Required vault secrets** — each `{ key, label, type }`. +- **Required tool permissions** — must be drawn from the canonical Pancake tool list + ([`docs/bundle-reference.md#tool-permissions`](../../../docs/bundle-reference.md#tool-permissions)). + Accepted keys today: `browser`, `exa` / `web_search` / `web_fetch`, `github`, + `google-workspace` / `google_workspace`, `notion`, `agentmail`, `vault`, + `preview-host` / `publish_preview`, `mcp-installer`, + `image-generation` / `image_generate` / `image`, `cron`. Anything else is rejected by + the validator. Slack and voice/TTS are intentionally excluded — those are user-facing + channels owned by the co-founder, not by a sub-agent. +- **Crons** — any scheduled jobs, and what each one does. +- **Catalog metadata** — `tags` for the marketplace card (no `token_intensity` — it is + deprecated and Pancake Cloud computes token usage automatically). + +## Step 3 — Scaffold + +Copy [`template/`](../../../template/) to `squads//`, then fill every file: + +- **`manifest.json`** — package descriptor only. `agents` is a string array of kebab ids. + No per-agent runtime config in this file. Delete optional sections the squad doesn't use. +- **`agents//agent.json`** for every agent — the per-agent runtime config (curated + subset of OpenClaw's `agents.list[]`). Required: `id`, `description`. `model` is a + string from `haiku`/`sonnet`/`opus`. `heartbeat` is an object with up to six allowed + sub-fields: `every`, `model`, `lightContext`, `isolatedSession`, `skipWhenBusy`, + `timeoutSeconds`. `every` is an OpenClaw duration in `ms`/`s`/`m`/`h` (e.g. `"30m"`, + `"2h"`, `"24h"`); plain strings (`"daily"`) and named values are rejected. Pod-level + fields like `prompt`, `target`, `directPolicy`, `session`, `to`, `ackMaxChars` are + rejected. Top-level optional fields: `skills`, `contextInjection`, `bootstrapMaxChars`, + `params`. Unknown fields anywhere are rejected. +- **`agents//IDENTITY.md`, `SOUL.md`, and `HEARTBEAT.md`** for every agent; add + `agents//MEMORY.md` if useful. `HEARTBEAT.md` is **required** when `agent.json` + declares a heartbeat — keep it out of `SOUL.md` (behaviour) and `MEMORY.md` (pointer + index). +- **Every skill file** referenced by `manifest.skills` or `agent.json#/skills`, in + SKILL.md format (frontmatter `name` + `description`, then a procedure written as steps). +- **`SQUAD.md`** — frontmatter is minimal: `tags` (recommended) and optional + `preview_image`. The body is the marketplace catalog's source of truth for per-agent + prose, so describe every agent here in user-facing language. +- **`ONBOARD.md`** — the runnable onboarding script the co-founder executes after deploy. +- Add or delete the optional `crons/jobs.json` and squad-wide `MEMORY.md` depending on + Step 2. +- **Strip every `` comment and placeholder** the template ships with. The + validator errors on any unresolved TODO marker outside `template/`. + +> If this repo has no `squads/` directory — i.e. it is a third-party self-host repo — scaffold +> at the **repo root** instead of under `squads//`. See +> [`docs/publishing.md`](../../../docs/publishing.md). + +## Step 4 — Bake in the conventions + +- Each agent is a **focused, single-lane specialist** that reports to the co-founder — not a + generalist. +- **Bounded tool output is a hard default.** Any agent that runs queries (SQL / HogQL / API) + or calls tools that can return large payloads must enforce result-size discipline in its + skills **and** `SOUL.md`: aggregate over enumerate, put a small explicit `LIMIT` on every + row-returning query, project named scalar fields (never `SELECT *` or a raw JSON blob), and + send wide or row-level extracts to a file rather than into the conversation. State the + rationale in the skill so it sticks: a single tool result over ~25k tokens overflows the + model context, **cannot be compacted away** (it exceeds the summarizer's per-message limit), + and wedges the agent in a fail→retry loop that burns the model fallback ladder until the + session is manually reset. This is a real production failure mode, not a hypothetical — see + `squads/posthog-squad/agents/posthog-agent/skills/posthog-mcp-toolkit.md → Result-size + discipline` for the reference implementation. +- `ONBOARD.md` is a **runnable script** the co-founder executes: collect secrets via + `vault_request`, connect identities via `browser_identity_add`, save answers to the agent's + `MEMORY.md`, and create + dispatch a first task. It must fit `estimated_setup_minutes`. +- `MEMORY.md` is a **thin index of pointers**, never a notebook. +- `HEARTBEAT.md` is the **imperative wake procedure** OpenClaw loads on every pulse — + not behaviour (that's `SOUL.md`), not pointers (that's `MEMORY.md`). It must require + the agent to **execute at least one task before closing the session** (no + orient-and-bail), and to write a **digest** to `memory/YYYY-MM-DD.md` before ending + the turn — what was done, what changed, what's still open, the next wake's first + move. `NO_REPLY` is only acceptable when nothing is actionable, with the reason + logged first. +- The **`SQUAD.md` body** is the catalog's per-agent prose surface — describe each + agent in user-facing language there (not in `manifest.json`). +- **Forbidden files**: do not create `AGENTS.md`, `USER.md`, `BOOTSTRAP.md`, or `BOOT.md` + inside the bundle — those are pod-managed by Pancake Cloud. `TOOLS.md` is allowed (it + is bundle-authored documentation). +- Crons target **only this squad's own agents**. +- **Squad crons run in the agent's *persistent* session — they cannot be isolated.** OpenClaw + has an ephemeral `sessionTarget: "isolated"` cron mode, but it requires the target *not* be a + named agent and `payload.kind: "agentTurn"` — and the squad installer rejects any cron whose + `sessionTarget` isn't one of the bundle's own agents (which it must be). So every squad cron + runs as `payload.kind: "systemEvent"` in that agent's main session, which **persists and + accumulates across runs**. Design for two consequences: (1) a cron run that emits an oversized + tool result wedges that main session with no sandbox to fall back on — bounded tool output + (above) is the only guard; (2) each cron run must **self-clean** — do the work, file results + to the wiki, write the daily digest, and close — so the persistent session does not grow + unbounded. `heartbeat.isolatedSession` gives *heartbeat wakes* a fresh session, but there is + **no equivalent for crons** — never assume a cron is sandboxed. +- A cron run with nothing to report must reply with the single literal token `NO_REPLY`. + +## Step 5 — Validate (mandatory gate) + +Validation is a **blocking gate**, not advisory. The bundle is not finished until the +validator exits 0 with no errors. + +```sh +node scripts/validate.mjs squads/ +``` + +- Run the validator **after every batch of edits**, not just at the end. The validator + is your test loop — it catches forbidden files, unresolved TODOs, schema drift, and + broken file references that compound if left until the end. +- Fix every error and re-run. Treat warnings the same way unless the user explicitly + accepts them (e.g. a deliberately tag-less private bundle). +- **Do not declare the bundle finished** until you have run the validator at least once + and seen it exit 0 on this specific bundle. + +## Step 6 — Hand off + +Tell the user the bundle is ready, summarize what was built, state the validator +outcome (the last exit-0 run on this bundle), and point them to +[`docs/publishing.md`](../../../docs/publishing.md) for getting it into the marketplace. diff --git a/.agents/skills/validate-squad/SKILL.md b/.agents/skills/validate-squad/SKILL.md new file mode 100644 index 0000000..e63ffa2 --- /dev/null +++ b/.agents/skills/validate-squad/SKILL.md @@ -0,0 +1,84 @@ +--- +name: validate-squad +description: Validate an Agent Squad bundle and fix what's broken — runs the repo validator, explains each error in plain language, and corrects the offending files. Use when the user wants to check, validate, or debug a squad bundle. +--- + +# Validate a squad + +Run the validator, explain what it found, and fix it. + +## Step 1 — Run the validator + +```sh +node scripts/validate.mjs # every squads/* bundle and template/ +node scripts/validate.mjs squads/ # one specific bundle +``` + +Scope it to a single bundle if the user named one. The validator exits non-zero if any +bundle has an error; warnings never fail the run. + +## Step 2 — Explain each error + +For every error, tell the user in plain language **what** is wrong and **why** it matters, +referencing [`docs/bundle-reference.md`](../../../docs/bundle-reference.md) for the rule. +The validator's checks fall into the following categories: + +- **Manifest schema** (e.g. `agents[0] "Geo Agent" must be kebab-case`) — a field in + `manifest.json` breaks a rule: bad kebab-case or semver, a missing required field, a + value outside an enum, a duplicate agent id, or `agents` is no longer an object array + (it must now be a string array of agent ids). +- **`agent.json` missing** (`agents//agent.json not found`) — every id in + `manifest.agents` must have a matching `agents//agent.json` file. +- **`agent.json` schema** (e.g. `agents//agent.json#/model must be one of: haiku, + sonnet, opus`) — the per-agent config is invalid. Common causes: + - Wrong `model` value (string enum `haiku`/`sonnet`/`opus`) — applies to both + top-level `model` and `heartbeat.model`. + - `heartbeat` written as a plain string instead of the object shape (e.g. + `"heartbeat": "daily"` instead of `"heartbeat": { "every": "24h" }`). + - `heartbeat.every` written as a named value (`"daily"`) instead of an OpenClaw duration + in `ms`/`s`/`m`/`h` (`"30m"`, `"2h"`, `"24h"`, `"0m"`). + - Unknown field on the agent or inside `heartbeat`. Only six heartbeat sub-fields are + accepted (`every`, `model`, `lightContext`, `isolatedSession`, `skipWhenBusy`, + `timeoutSeconds`); pod-level fields like `prompt`, `target`, `directPolicy`, + `session`, `to`, `ackMaxChars` are rejected because they're not authorable from a + bundle. + - `id` not matching the directory name. +- **Referenced-file errors** — a file the manifest or agent.json points to (`SQUAD.md`, + `ONBOARD.md`, a skill, `IDENTITY.md`, `SOUL.md`, `HEARTBEAT.md` when the agent has a + heartbeat) is missing, is a symlink, is not a regular file, or resolves outside the + bundle root. +- **Unknown tool permission** (e.g. `required_tool_permissions[2] "message" is not an + accepted tool key`) — an entry in `manifest.required_tool_permissions` is not in the + canonical Pancake tool list (see [`bundle-reference.md#tool-permissions`](../../../docs/bundle-reference.md#tool-permissions)). + Common migrations: `browser_task`/`browser_open`/`browser_action` → `browser`; + `message`, `slack-block-kit`, `voice`, `tts` → **delete** (Slack and voice are + user-facing channels owned by the co-founder, not a squad agent). If the bundle still + carries `slack-block-kit` from an earlier draft, that's why — drop it. +- **Targeting errors** (`crons/jobs.json`) — a cron's `sessionTarget` names an agent the + squad does not declare. Squad crons may target only the squad's own agents. +- **Forbidden file** (e.g. `agents//USER.md forbidden filename`) — the bundle + contains a file named `AGENTS.md`, `USER.md`, `BOOTSTRAP.md`, or `BOOT.md`. Those are + pod-managed by Pancake Cloud and must not appear inside a bundle. Delete the file. + `TOOLS.md` is *allowed* and is not flagged. +- **Deprecated field** (e.g. `SQUAD.md frontmatter has a deprecated 'token_intensity:' + line`) — `token_intensity` has been removed from the contract. Pancake Cloud computes + token usage automatically; delete the line. +- **Unresolved TODO** (e.g. `SQUAD.md unresolved TODO marker on line 12`) — the bundle + still contains `