@synap-core/cli 1.8.0 → 1.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/agent-chat.d.ts +47 -0
- package/dist/commands/agent-chat.js +250 -0
- package/dist/commands/agent-chat.js.map +1 -0
- package/dist/commands/agent-run.js +3 -4
- package/dist/commands/agent-run.js.map +1 -1
- package/dist/commands/agents.js +85 -46
- package/dist/commands/agents.js.map +1 -1
- package/dist/commands/automation.js +2 -1
- package/dist/commands/automation.js.map +1 -1
- package/dist/commands/bridge-setup.d.ts +66 -0
- package/dist/commands/bridge-setup.js +1112 -0
- package/dist/commands/bridge-setup.js.map +1 -0
- package/dist/commands/cap-connections.d.ts +28 -0
- package/dist/commands/cap-connections.js +224 -0
- package/dist/commands/cap-connections.js.map +1 -0
- package/dist/commands/capability.d.ts +89 -0
- package/dist/commands/capability.js +1594 -0
- package/dist/commands/capability.js.map +1 -0
- package/dist/commands/centrality.d.ts +20 -0
- package/dist/commands/centrality.js +95 -0
- package/dist/commands/centrality.js.map +1 -0
- package/dist/commands/connect.d.ts +2 -0
- package/dist/commands/connect.js +16 -35
- package/dist/commands/connect.js.map +1 -1
- package/dist/commands/context.js +6 -7
- package/dist/commands/context.js.map +1 -1
- package/dist/commands/data-extra.d.ts +1 -0
- package/dist/commands/data-extra.js +41 -14
- package/dist/commands/data-extra.js.map +1 -1
- package/dist/commands/data.d.ts +4 -4
- package/dist/commands/data.js +254 -187
- package/dist/commands/data.js.map +1 -1
- package/dist/commands/diagnose.d.ts +20 -0
- package/dist/commands/diagnose.js +186 -0
- package/dist/commands/diagnose.js.map +1 -0
- package/dist/commands/digest.d.ts +17 -0
- package/dist/commands/digest.js +122 -0
- package/dist/commands/digest.js.map +1 -0
- package/dist/commands/discover.d.ts +2 -0
- package/dist/commands/discover.js +25 -8
- package/dist/commands/discover.js.map +1 -1
- package/dist/commands/doc.d.ts +14 -0
- package/dist/commands/doc.js +61 -4
- package/dist/commands/doc.js.map +1 -1
- package/dist/commands/doctor.d.ts +21 -0
- package/dist/commands/doctor.js +189 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/events.js +5 -2
- package/dist/commands/events.js.map +1 -1
- package/dist/commands/explain.d.ts +1 -1
- package/dist/commands/explain.js +18 -15
- package/dist/commands/explain.js.map +1 -1
- package/dist/commands/facet.d.ts +29 -0
- package/dist/commands/facet.js +113 -0
- package/dist/commands/facet.js.map +1 -0
- package/dist/commands/graph.js +7 -4
- package/dist/commands/graph.js.map +1 -1
- package/dist/commands/import.d.ts +38 -0
- package/dist/commands/import.js +471 -0
- package/dist/commands/import.js.map +1 -0
- package/dist/commands/init.js +35 -16
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/keys.js +3 -4
- package/dist/commands/keys.js.map +1 -1
- package/dist/commands/knowledge.d.ts +8 -0
- package/dist/commands/knowledge.js +308 -33
- package/dist/commands/knowledge.js.map +1 -1
- package/dist/commands/launch.d.ts +50 -0
- package/dist/commands/launch.js +790 -0
- package/dist/commands/launch.js.map +1 -0
- package/dist/commands/lens.d.ts +45 -0
- package/dist/commands/lens.js +386 -0
- package/dist/commands/lens.js.map +1 -0
- package/dist/commands/market-authoring.d.ts +45 -0
- package/dist/commands/market-authoring.js +225 -0
- package/dist/commands/market-authoring.js.map +1 -0
- package/dist/commands/market.d.ts +224 -0
- package/dist/commands/market.js +1643 -0
- package/dist/commands/market.js.map +1 -0
- package/dist/commands/mcp.d.ts +64 -0
- package/dist/commands/mcp.js +265 -0
- package/dist/commands/mcp.js.map +1 -0
- package/dist/commands/observe.js +14 -11
- package/dist/commands/observe.js.map +1 -1
- package/dist/commands/open.d.ts +21 -4
- package/dist/commands/open.js +45 -4
- package/dist/commands/open.js.map +1 -1
- package/dist/commands/pod.d.ts +100 -0
- package/dist/commands/pod.js +359 -0
- package/dist/commands/pod.js.map +1 -0
- package/dist/commands/pods.d.ts +15 -0
- package/dist/commands/pods.js +233 -17
- package/dist/commands/pods.js.map +1 -1
- package/dist/commands/proposals-actions.js +43 -3
- package/dist/commands/proposals-actions.js.map +1 -1
- package/dist/commands/purge.d.ts +23 -0
- package/dist/commands/purge.js +148 -0
- package/dist/commands/purge.js.map +1 -0
- package/dist/commands/raycast.d.ts +15 -0
- package/dist/commands/raycast.js +153 -0
- package/dist/commands/raycast.js.map +1 -0
- package/dist/commands/sessions.js +47 -22
- package/dist/commands/sessions.js.map +1 -1
- package/dist/commands/skill-manage.d.ts +21 -0
- package/dist/commands/skill-manage.js +195 -0
- package/dist/commands/skill-manage.js.map +1 -0
- package/dist/commands/skills-commands.js +2 -1
- package/dist/commands/skills-commands.js.map +1 -1
- package/dist/commands/skills.js +7 -4
- package/dist/commands/skills.js.map +1 -1
- package/dist/commands/status.d.ts +3 -1
- package/dist/commands/status.js +166 -14
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/statusline.d.ts +24 -0
- package/dist/commands/statusline.js +450 -0
- package/dist/commands/statusline.js.map +1 -0
- package/dist/commands/subscribe.js +2 -2
- package/dist/commands/subscribe.js.map +1 -1
- package/dist/commands/template.d.ts +42 -0
- package/dist/commands/template.js +191 -0
- package/dist/commands/template.js.map +1 -0
- package/dist/commands/tools.d.ts +30 -0
- package/dist/commands/tools.js +315 -0
- package/dist/commands/tools.js.map +1 -0
- package/dist/commands/upload.d.ts +30 -0
- package/dist/commands/upload.js +155 -0
- package/dist/commands/upload.js.map +1 -0
- package/dist/commands/versions.d.ts +27 -0
- package/dist/commands/versions.js +277 -0
- package/dist/commands/versions.js.map +1 -0
- package/dist/commands/view.js +3 -2
- package/dist/commands/view.js.map +1 -1
- package/dist/commands/whoami.d.ts +21 -0
- package/dist/commands/whoami.js +129 -0
- package/dist/commands/whoami.js.map +1 -0
- package/dist/index.js +894 -60
- package/dist/index.js.map +1 -1
- package/dist/lib/approval-poll.d.ts +42 -0
- package/dist/lib/approval-poll.js +52 -0
- package/dist/lib/approval-poll.js.map +1 -0
- package/dist/lib/auth.d.ts +29 -6
- package/dist/lib/auth.js +105 -94
- package/dist/lib/auth.js.map +1 -1
- package/dist/lib/bundle-version.d.ts +11 -0
- package/dist/lib/bundle-version.js +33 -0
- package/dist/lib/bundle-version.js.map +1 -0
- package/dist/lib/capture-lane.d.ts +30 -12
- package/dist/lib/capture-lane.js +73 -14
- package/dist/lib/capture-lane.js.map +1 -1
- package/dist/lib/capture-structure.d.ts +123 -0
- package/dist/lib/capture-structure.js +57 -0
- package/dist/lib/capture-structure.js.map +1 -0
- package/dist/lib/cp-packages.d.ts +177 -0
- package/dist/lib/cp-packages.js +389 -0
- package/dist/lib/cp-packages.js.map +1 -0
- package/dist/lib/describe-lens.d.ts +46 -0
- package/dist/lib/describe-lens.js +33 -0
- package/dist/lib/describe-lens.js.map +1 -0
- package/dist/lib/hub-client.d.ts +91 -1
- package/dist/lib/hub-client.js +565 -22
- package/dist/lib/hub-client.js.map +1 -1
- package/dist/lib/id.d.ts +23 -0
- package/dist/lib/id.js +35 -0
- package/dist/lib/id.js.map +1 -0
- package/dist/lib/installed.d.ts +51 -0
- package/dist/lib/installed.js +70 -0
- package/dist/lib/installed.js.map +1 -0
- package/dist/lib/next-steps.d.ts +61 -0
- package/dist/lib/next-steps.js +146 -0
- package/dist/lib/next-steps.js.map +1 -0
- package/dist/lib/pod.d.ts +144 -22
- package/dist/lib/pod.js +302 -64
- package/dist/lib/pod.js.map +1 -1
- package/dist/lib/project-ref.d.ts +95 -0
- package/dist/lib/project-ref.js +144 -0
- package/dist/lib/project-ref.js.map +1 -0
- package/dist/lib/project.d.ts +35 -0
- package/dist/lib/project.js +39 -0
- package/dist/lib/project.js.map +1 -0
- package/dist/lib/session-lens.d.ts +33 -0
- package/dist/lib/session-lens.js +76 -0
- package/dist/lib/session-lens.js.map +1 -0
- package/dist/lib/skill-import.d.ts +40 -0
- package/dist/lib/skill-import.js +203 -0
- package/dist/lib/skill-import.js.map +1 -0
- package/dist/lib/skills-installer.d.ts +17 -6
- package/dist/lib/skills-installer.js +133 -19
- package/dist/lib/skills-installer.js.map +1 -1
- package/dist/lib/suite.d.ts +28 -0
- package/dist/lib/suite.js +29 -0
- package/dist/lib/suite.js.map +1 -0
- package/dist/lib/superwhisper-import.d.ts +40 -0
- package/dist/lib/superwhisper-import.js +389 -0
- package/dist/lib/superwhisper-import.js.map +1 -0
- package/dist/lib/targets.d.ts +49 -1
- package/dist/lib/targets.js +420 -288
- package/dist/lib/targets.js.map +1 -1
- package/dist/lib/template-file.d.ts +74 -0
- package/dist/lib/template-file.js +140 -0
- package/dist/lib/template-file.js.map +1 -0
- package/dist/lib/unwrapList.d.ts +1 -0
- package/dist/lib/unwrapList.js +20 -0
- package/dist/lib/unwrapList.js.map +1 -0
- package/dist/utils/logger.d.ts +2 -0
- package/dist/utils/logger.js +10 -2
- package/dist/utils/logger.js.map +1 -1
- package/node_modules/@synap/hub-rest-client/dist/index.cjs +414 -34
- package/node_modules/@synap/hub-rest-client/dist/index.d.cts +762 -22
- package/node_modules/@synap/hub-rest-client/dist/index.d.ts +762 -22
- package/node_modules/@synap/hub-rest-client/dist/index.js +414 -34
- package/node_modules/@synap/hub-rest-client/package.json +1 -1
- package/node_modules/@synap/hub-rest-client/src/client.ts +525 -37
- package/node_modules/@synap/hub-rest-client/src/index.ts +42 -0
- package/node_modules/@synap/hub-rest-client/src/setup.ts +57 -1
- package/node_modules/@synap/hub-rest-client/src/types.ts +697 -37
- package/package.json +11 -5
- package/skills/agent-os/SKILL.md +218 -0
- package/skills/manifest.json +5 -0
- package/skills/onboard/SKILL.md +193 -0
- package/skills/synap/SKILL.md +1284 -58
- package/skills/synap/_order.txt +37 -0
- package/skills/synap/_skill.yaml +24 -0
- package/skills/synap/authentication.md +10 -0
- package/skills/synap/automations.md +264 -0
- package/skills/synap/capabilities.md +107 -0
- package/skills/synap/capture.md +50 -142
- package/skills/synap/cli-operations.md +107 -0
- package/skills/synap/common-mistakes.md +13 -0
- package/skills/synap/content-os.md +83 -0
- package/skills/synap/creative-loop.md +43 -0
- package/skills/synap/crm.md +117 -0
- package/skills/synap/diagnostics.md +35 -0
- package/skills/synap/digesting-a-channel.md +63 -0
- package/skills/synap/document-embeds.md +123 -0
- package/skills/synap/escalation-ladder.md +71 -0
- package/skills/synap/focus-sessions.md +47 -0
- package/skills/synap/governance-rules.md +64 -0
- package/skills/synap/governance.md +6 -6
- package/skills/synap/graph-gardening.md +21 -0
- package/skills/synap/inline-patterns.md +38 -0
- package/skills/synap/lenses.md +38 -0
- package/skills/synap/linking-principle.md +39 -0
- package/skills/synap/linking.md +1 -0
- package/skills/synap/mental-model.md +45 -0
- package/skills/synap/more.md +7 -0
- package/skills/synap/multi-entity-capture.md +12 -0
- package/skills/synap/next-action.md +37 -0
- package/skills/synap/north-star.md +17 -0
- package/skills/synap/operating-mode-rules.md +45 -0
- package/skills/synap/operating-mode.md +9 -0
- package/skills/synap/quick-reference.md +67 -0
- package/skills/synap/reading.md +43 -0
- package/skills/synap/recap.md +21 -0
- package/skills/synap/reflexes.md +46 -0
- package/skills/synap/response-style.md +21 -0
- package/skills/synap/scope.md +13 -0
- package/skills/synap/showing.md +17 -0
- package/skills/synap/user-model.md +25 -0
- package/skills/synap/viewframe-cells.md +290 -0
- package/skills/synap/work-flow.md +113 -0
- package/skills/synap/worked-examples.md +74 -0
- package/skills/synap/workspace-design.md +45 -0
- package/skills/synap/workspace-edges.md +49 -0
- package/skills/synap/writes.md +213 -0
- package/skills/synap-app/SKILL.md +319 -0
- package/skills/synap-app/_order.txt +5 -0
- package/skills/synap-app/_skill.yaml +20 -0
- package/skills/synap-app/creating-the-base-app.md +64 -0
- package/skills/synap-app/governance.md +42 -0
- package/skills/synap-app/install-commands.md +55 -0
- package/skills/synap-app/overview.md +50 -0
- package/skills/synap-app/using-the-sdk.md +73 -0
- package/skills/synap-market/SKILL.md +335 -0
- package/skills/synap-market/_order.txt +5 -0
- package/skills/synap-market/_skill.yaml +24 -0
- package/skills/synap-market/author-and-publish.md +75 -0
- package/skills/synap-market/discover-and-fetch.md +59 -0
- package/skills/synap-market/governance-and-catalog.md +56 -0
- package/skills/synap-market/install.md +55 -0
- package/skills/synap-market/overview.md +51 -0
- package/skills/synap-schema/SKILL.md +97 -6
- package/skills/synap-schema/_order.txt +13 -0
- package/skills/synap-schema/_skill.yaml +22 -0
- package/skills/synap-schema/before-you-touch.md +14 -0
- package/skills/synap-schema/common-mistakes.md +9 -0
- package/skills/synap-schema/creating-profiles.md +17 -0
- package/skills/synap-schema/discover-profiles.md +24 -0
- package/skills/synap-schema/entity-scope.md +8 -0
- package/skills/synap-schema/extend-vs-create.md +31 -0
- package/skills/synap-schema/more.md +6 -0
- package/skills/synap-schema/overlay-properties.md +22 -0
- package/skills/synap-schema/profiles.md +3 -0
- package/skills/synap-schema/property-defs.md +29 -0
- package/skills/synap-schema/read-before-write.md +50 -0
- package/skills/synap-schema/relations.md +18 -0
- package/skills/synap-schema/worked-example.md +30 -0
- package/skills/synap-ui/SKILL.md +26 -2
- package/skills/synap-ui/_order.txt +13 -0
- package/skills/synap-ui/_skill.yaml +23 -0
- package/skills/synap-ui/ai-companion.md +27 -0
- package/skills/synap-ui/arranging-bento.md +8 -0
- package/skills/synap-ui/before-you-build.md +20 -0
- package/skills/synap-ui/bento-layouts.md +35 -0
- package/skills/synap-ui/common-mistakes.md +10 -0
- package/skills/synap-ui/creating-views.md +26 -0
- package/skills/synap-ui/four-builds.md +24 -0
- package/skills/synap-ui/more.md +7 -0
- package/skills/synap-ui/proposing-vs-extending.md +11 -0
- package/skills/synap-ui/view-list.md +24 -0
- package/skills/synap-ui/views.md +3 -0
- package/skills/synap-ui/worked-example.md +18 -0
- package/skills/synap-ui/workspaces.md +47 -0
- package/templates/automations/bookmark-enrichment.automation.json +44 -0
- package/templates/automations/mail-feed.automation.json +86 -0
- package/templates/automations/url-bookmark-capture.automation.json +70 -0
- package/templates/skills/README.md +21 -0
- package/templates/skills/authoring-automations/SKILL.md +95 -0
- package/templates/skills/authoring-automations/reference/node-matrix.md +49 -0
- package/templates/skills/authoring-capabilities/SKILL.md +93 -0
- package/templates/skills/authoring-capabilities/reference/template-anatomy.md +70 -0
- package/templates/skills/authoring-playbooks/SKILL.md +102 -0
- package/templates/skills/authoring-playbooks/reference/stages-contract.md +35 -0
- package/templates/skills/authoring-playbooks/reference/worked-example.md +64 -0
- package/templates/skills/bookmark-enrichment/SKILL.md +40 -0
- package/templates/skills/coordinating-agents/SKILL.md +32 -0
- package/templates/skills/coordinating-branches/SKILL.md +27 -0
- package/templates/skills/mapping-the-server/SKILL.md +54 -0
- package/templates/skills/reading-client-progress/SKILL.md +65 -0
- package/templates/skills/routing-to-channels/SKILL.md +54 -0
- package/templates/skills/stellar-scf-grants-advisor/ASSOCIATE-CHEATSHEET.md +133 -0
- package/templates/skills/stellar-scf-grants-advisor/ASSOCIATE-ONBOARDING-GUIDE.md +761 -0
- package/templates/skills/stellar-scf-grants-advisor/CLIENT-FAQ.md +181 -0
- package/templates/skills/stellar-scf-grants-advisor/PARTNER-HANDOVER.md +130 -0
- package/templates/skills/stellar-scf-grants-advisor/SKILL.md +102 -0
- package/templates/skills/stellar-scf-grants-advisor/examples/README.md +43 -0
- package/templates/skills/stellar-scf-grants-advisor/examples/chat-summary-templates.md +158 -0
- package/templates/skills/stellar-scf-grants-advisor/examples/corpus-comparable-rows.md +136 -0
- package/templates/skills/stellar-scf-grants-advisor/examples/q10-team-rewrites.md +109 -0
- package/templates/skills/stellar-scf-grants-advisor/examples/q2-description-rewrites.md +88 -0
- package/templates/skills/stellar-scf-grants-advisor/examples/q6-integration-rewrites.md +107 -0
- package/templates/skills/stellar-scf-grants-advisor/examples/tranche-structures.md +176 -0
- package/templates/skills/stellar-scf-grants-advisor/reference/01-methodology.md +96 -0
- package/templates/skills/stellar-scf-grants-advisor/reference/02-scoring-framework.md +199 -0
- package/templates/skills/stellar-scf-grants-advisor/reference/03-rejection-patterns.md +241 -0
- package/templates/skills/stellar-scf-grants-advisor/reference/04-winner-patterns.md +120 -0
- package/templates/skills/stellar-scf-grants-advisor/reference/05-comeback-patterns.md +92 -0
- package/templates/skills/stellar-scf-grants-advisor/reference/06-budget-benchmarks.md +125 -0
- package/templates/skills/stellar-scf-grants-advisor/reference/07-integration-list.md +147 -0
- package/templates/skills/stellar-scf-grants-advisor/reference/08-abstract-fields.md +258 -0
- package/templates/skills/stellar-scf-grants-advisor/reference/09-build-fields.md +259 -0
- package/templates/skills/stellar-scf-grants-advisor/reference/10-corpus-winners.md +135 -0
- package/templates/skills/stellar-scf-grants-advisor/reference/11-corpus-rejects.md +267 -0
- package/templates/skills/stellar-scf-grants-advisor/reference/12-client-communication.md +131 -0
- package/templates/skills/stellar-scf-grants-advisor/reference/13-excel-output-spec.md +199 -0
- package/templates/skills/stellar-scf-grants-advisor/reference/14-worked-examples.md +160 -0
- package/templates/skills/stellar-scf-grants-advisor/templates/abstract-review-builder.py +253 -0
- package/templates/skills/stellar-scf-grants-advisor/templates/build-review-builder.py +213 -0
- package/dist/commands/connectors.d.ts +0 -31
- package/dist/commands/connectors.js +0 -276
- package/dist/commands/connectors.js.map +0 -1
- package/dist/commands/finish.d.ts +0 -25
- package/dist/commands/finish.js +0 -274
- package/dist/commands/finish.js.map +0 -1
- package/dist/commands/openclaw.d.ts +0 -40
- package/dist/commands/openclaw.js +0 -1148
- package/dist/commands/openclaw.js.map +0 -1
- package/dist/commands/security-audit.d.ts +0 -12
- package/dist/commands/security-audit.js +0 -100
- package/dist/commands/security-audit.js.map +0 -1
- package/dist/lib/hardening.d.ts +0 -18
- package/dist/lib/hardening.js +0 -214
- package/dist/lib/hardening.js.map +0 -1
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Automation node matrix (exhaustive)
|
|
2
|
+
|
|
3
|
+
Every node is `{ id, type, position: {x,y}, data }`. Edges are `{ id, source, target }`. `data` shape varies by `type`.
|
|
4
|
+
|
|
5
|
+
## Triggers (4)
|
|
6
|
+
|
|
7
|
+
| triggerType | triggerConfig | Notes |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| `cron` | `{ expression: "0 9 * * *" }` | Pod-wide scheduler polls every minute → minute granularity, no sub-minute. |
|
|
10
|
+
| `event` | `{ eventPattern, filters }` | Patterns: `entities.*`, `focus_session.stage_changed.*`, `external_message.received.*`, etc. `filters` narrows by payload fields (e.g. `{ provider: "discord" }`). |
|
|
11
|
+
| `webhook` | `{ webhookSubscriptionId }` | Fires on inbound webhook delivery. |
|
|
12
|
+
| `manual` | — | On-demand run by user/agent. |
|
|
13
|
+
|
|
14
|
+
## Nodes (14)
|
|
15
|
+
|
|
16
|
+
| type | Purpose | Key fields / config |
|
|
17
|
+
|---|---|---|
|
|
18
|
+
| `trigger` | Entry node mirroring the trigger | `{ triggerType, config }` |
|
|
19
|
+
| `command` | Free-form AI step via IS | prompt; UNTYPED output — strongly prefer a `skill` for extraction. `command → loop` is a best-effort fallback only (ship `status: "draft"` + reliability caveat; output shape not guaranteed, loop may resolve `[]`) |
|
|
20
|
+
| `condition` | Branch on a safe comparison | safe comparators (eq, neq, gt, lt, contains…); no arbitrary eval |
|
|
21
|
+
| `delay` | Pause the flow | `5m` \| `1h` \| `1d` \| `1w` |
|
|
22
|
+
| `output` | Side effects (see subtypes below) | `outputType` + `config` |
|
|
23
|
+
| `loop` | Iterate an array | `iteratorExpression` (RAW path); cap **100**. `itemVariable` is currently IGNORED by the executor (it only binds `context.loop.item`) — reference items as `{{loop.item.*}}`, not the named var |
|
|
24
|
+
| `transform` | String transform | `expression: "<raw path> \| op"`; ops: `uppercase`, `lowercase`, `json`, `trim`, `url_extract` |
|
|
25
|
+
| `fetch` | HTTP request | URL, method, vault headers; 30s timeout; auto-JSON-parses body |
|
|
26
|
+
| `query` | Read entities from the pod | profile + filter |
|
|
27
|
+
| `switch` | Multi-way branch | cases on a value |
|
|
28
|
+
| `skill` | Run an IS skill (gated) | skill name + args; returns STRUCTURED data — use for extraction |
|
|
29
|
+
| `capability` | Run a capability verb → skill (gated) | verb resolves to a skill |
|
|
30
|
+
| `sub_automation` | Call another automation | depth limit **5** |
|
|
31
|
+
| `playbook_run` | Start a playbook | playbook ref + params/subject |
|
|
32
|
+
|
|
33
|
+
## `output` subtypes
|
|
34
|
+
|
|
35
|
+
| outputType | config | Notes |
|
|
36
|
+
|---|---|---|
|
|
37
|
+
| `entity_create` | `{ profileSlug, title, dedupeBy, properties }` | Governed (proposal-gated). Empty/duplicate guarded. **`dedupeBy` is a SINGLE key**, not a list. |
|
|
38
|
+
| `entity_update` | target + properties | Governed. |
|
|
39
|
+
| `webhook` | `{ url, method, headers, body }` | POST to ANY URL; headers can pull from the vault. The ONLY way to reach Discord from an automation. |
|
|
40
|
+
| `notification` | message/target | In-app notification. |
|
|
41
|
+
| `channel_message` | channel + content | Inserts an internal `messages` row ONLY. Does NOT relay to Discord/Telegram. |
|
|
42
|
+
|
|
43
|
+
## Data-flow paths
|
|
44
|
+
|
|
45
|
+
- `{{trigger.payload.x}}` — trigger event fields.
|
|
46
|
+
- `{{steps.<nodeId>.output.x}}` — a prior node's output.
|
|
47
|
+
- `{{loop.item}}`, `{{loop.index}}` — inside a loop body.
|
|
48
|
+
|
|
49
|
+
**Resolution rule:** `{{…}}` interpolation goes through `resolveTemplate`, which STRINGIFIES (lossy for objects/arrays). The **loop `iteratorExpression`** and **transform `expression`** input resolve the path RAW — that is why looping over `steps.extract.output.events` works on the real array. Build/iterate structured data with those raw-path fields; reserve `{{…}}` for string slots.
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: authoring-capabilities
|
|
3
|
+
description: Authors a Synap Capability template — the delivery vehicle that bundles tools + skills + playbooks + automations into one applyable .capability.json. Use whenever the user wants to connect a service (OAuth or API key), package a reusable know-how/process pack, ship a new connector, or assemble several skills and a process into one installable bundle. This is the top of the authoring stack: pick the pack shape, then author the playbook (process) and automations (when) inside it.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Authoring Capabilities
|
|
7
|
+
|
|
8
|
+
A **Capability** is the delivery vehicle in Synap: a named container that bundles **tools** (connections), **skills** (know-how/code), **playbooks** (processes), and optionally **automations** (when), applied as one unit. This skill teaches the template file, the skill kinds, the connector shapes, and how to seed it. It is the top of the three-skill authoring stack — compose it with `authoring-playbooks` and `authoring-automations`.
|
|
9
|
+
|
|
10
|
+
Read `reference/template-anatomy.md` for the full field reference and reference templates.
|
|
11
|
+
|
|
12
|
+
## The file
|
|
13
|
+
|
|
14
|
+
`synap-control-plane-api/src/seeds/capability-templates/<key>.capability.json`:
|
|
15
|
+
|
|
16
|
+
```jsonc
|
|
17
|
+
{
|
|
18
|
+
"key": "my-connector",
|
|
19
|
+
"name": "My Connector",
|
|
20
|
+
"description": "What this bundle gives an agent and when to use it.",
|
|
21
|
+
"params": [ /* { name, label, type, required?, default?, description } */ ],
|
|
22
|
+
"vault": [ /* secrets to encrypt */ ],
|
|
23
|
+
"tools": [ /* connectors */ ],
|
|
24
|
+
"skills": [ /* know-how + code */ ],
|
|
25
|
+
"playbooks": [ /* processes — REQUIRE a workspaceId at apply time */ ],
|
|
26
|
+
"automations": [ /* optional WHEN→THEN flows */ ]
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Materialization order (idempotent)
|
|
31
|
+
|
|
32
|
+
`createCapabilityFromDefinition()` applies parts in dependency order:
|
|
33
|
+
|
|
34
|
+
1. **vault** — encrypt each secret → it becomes referenceable as `vault://<id>` by its `ref`.
|
|
35
|
+
2. **tools** — created governed. A tool's `credentialRef` resolves: a `ref` name → `vault://<id>`, or `nango://<provider>` for OAuth. A tool's **verb catalog is DERIVED** from the skills that `requires` it.
|
|
36
|
+
3. **skills** — created (instruction skills injected as prompt; code skills born `approved: false`).
|
|
37
|
+
4. **playbooks** — created LAST among content; they **REQUIRE a `workspaceId`** (a playbook is workspace-scoped).
|
|
38
|
+
5. **container** — the capability itself, with `member_of` links wiring all parts together.
|
|
39
|
+
|
|
40
|
+
Re-applying is idempotent — existing parts are matched, not duplicated.
|
|
41
|
+
|
|
42
|
+
## Skill kinds — pick the right one
|
|
43
|
+
|
|
44
|
+
| `kind` | What it is | When to use |
|
|
45
|
+
|---|---|---|
|
|
46
|
+
| `instruction` | Markdown injected into the agent's prompt (the `code`/body field holds the text) | Pure know-how: methodology, rules, how to draft/classify. No execution, no connector calls. |
|
|
47
|
+
| `code` | JS run in the IS isolate (sandboxed). Born `approved: false`. | Executable logic: fetch + transform + propose entities. Needs review before it runs. |
|
|
48
|
+
| `provider` | Declarative `providerSpec` (HTTP), run **in-process Tier-1** — NOT via the IS. | A trusted, declarative HTTP verb (e.g. a provider call) that doesn't need the AI isolate. Lowest latency. |
|
|
49
|
+
|
|
50
|
+
**`provider`-kind skills work only via the SEED-FILE path.** The inline Hub `POST /api/hub/capabilities/apply { definition }` route validates skills with a `SkillDefSchema` that accepts only `instruction` | `code` — so a `provider` skill passed inline is rejected. To ship a `provider` skill, seed it from a `<key>.capability.json` template (the seed path), not via an inline `definition`.
|
|
51
|
+
|
|
52
|
+
## Connector shapes — Nango (OAuth) vs vault-generic (API key)
|
|
53
|
+
|
|
54
|
+
| | Nango / OAuth | Vault-generic / API key |
|
|
55
|
+
|---|---|---|
|
|
56
|
+
| tool `kind` | `provider` | `api` |
|
|
57
|
+
| `credentialRef` | `nango://<provider>` | a `ref` → `vault://<id>` |
|
|
58
|
+
| `vault[]` | empty (Nango holds the token) | one entry (the API key) |
|
|
59
|
+
| tool `config` | provider-defined | `{ baseUrl, auth: { in, name, prefix } }` |
|
|
60
|
+
| Reference template | `nango-google.capability.json` | `generic-apikey.capability.json` |
|
|
61
|
+
|
|
62
|
+
**Reference templates (the molds to clone):**
|
|
63
|
+
- `nango-google` — Nango/OAuth connector.
|
|
64
|
+
- `cal-com` — vault/API-key connector.
|
|
65
|
+
- `agency-skills` — instruction-only pack + 2 playbooks. **The mold for a know-how + process pack.**
|
|
66
|
+
- `generic-apikey` — the blueprint to clone for any new vault-backed connector.
|
|
67
|
+
|
|
68
|
+
**Builtin `web_fetch` / `web_search` are always available** — no template needed just to read a URL.
|
|
69
|
+
|
|
70
|
+
## Seeding the capability
|
|
71
|
+
|
|
72
|
+
Two ways:
|
|
73
|
+
|
|
74
|
+
- **Via the bridge:** add the key to `AGENCY_CAPABILITY_PLAN` in `synap-cli/src/commands/bridge-setup.ts`. Set `workspaceScoped: true` if it bundles playbooks (so the bridge applies it WITH a workspace).
|
|
75
|
+
- **Directly:** `POST /api/hub/capabilities/apply` with `{ templateKey | definition, params, workspaceId }`.
|
|
76
|
+
|
|
77
|
+
## How the three authoring skills compose
|
|
78
|
+
|
|
79
|
+
A subagent given a plain goal ("build a process for X") works top-down:
|
|
80
|
+
|
|
81
|
+
1. **authoring-capabilities** (this skill) → pick the pack shape and the connectors it needs (Nango? API key? instruction-only?).
|
|
82
|
+
2. **authoring-playbooks** → design the process: ordered stages, subject, grants.
|
|
83
|
+
3. **authoring-automations** → design the WHEN: the trigger(s) that fire the playbook and any fan-out flows.
|
|
84
|
+
4. **Emit** the `.capability.json` (with `skills[]` + `playbooks[]`) plus any `*.automation.json`, then seed via the plan or `apply`.
|
|
85
|
+
|
|
86
|
+
## Authoring checklist
|
|
87
|
+
|
|
88
|
+
1. Choose the shape: connector (Nango/API key) or pure know-how/process pack.
|
|
89
|
+
2. Declare `params` and `vault` (empty for Nango / instruction-only).
|
|
90
|
+
3. Add `tools` with the right `credentialRef`; let verbs derive from skills' `requires`.
|
|
91
|
+
4. Add `skills` — pick `instruction` / `code` / `provider` per skill.
|
|
92
|
+
5. Add `playbooks` (remember: needs a workspaceId) and optional `automations`.
|
|
93
|
+
6. Seed via `AGENCY_CAPABILITY_PLAN` (`workspaceScoped` matching whether it has playbooks) or `POST /api/hub/capabilities/apply`.
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# Capability template anatomy
|
|
2
|
+
|
|
3
|
+
File: `synap-control-plane-api/src/seeds/capability-templates/<key>.capability.json`. Top-level keys: `key`, `name`, `description`, `params`, `vault`, `tools`, `skills`, `playbooks`, `automations?`.
|
|
4
|
+
|
|
5
|
+
## params
|
|
6
|
+
|
|
7
|
+
```jsonc
|
|
8
|
+
{ "name": "apiKey", "label": "API key", "type": "text", "required": true,
|
|
9
|
+
"default": "…", "description": "…" }
|
|
10
|
+
```
|
|
11
|
+
Param values are interpolated into the rest of the template as `{{paramName}}` (and `{{name}}` = the capability name). `type`: `text` | `number` | `entity` | `choice` | `boolean`.
|
|
12
|
+
|
|
13
|
+
## vault
|
|
14
|
+
|
|
15
|
+
```jsonc
|
|
16
|
+
{ "ref": "apiKeySecret", "name": "{{name}} API key", "value": "{{apiKey}}",
|
|
17
|
+
"type": "api_key", "description": "…" }
|
|
18
|
+
```
|
|
19
|
+
Each entry is encrypted at apply time and becomes referenceable as `vault://<id>` via its `ref`. **Nango / instruction-only capabilities have an empty `vault[]`.**
|
|
20
|
+
|
|
21
|
+
## tools
|
|
22
|
+
|
|
23
|
+
```jsonc
|
|
24
|
+
// vault-backed (API key)
|
|
25
|
+
{ "name": "generic_api", "kind": "api", "credentialRef": "apiKeySecret",
|
|
26
|
+
"executor": "is-agent",
|
|
27
|
+
"config": { "baseUrl": "{{baseUrl}}",
|
|
28
|
+
"auth": { "in": "header", "name": "Authorization", "prefix": "Bearer " } } }
|
|
29
|
+
|
|
30
|
+
// Nango (OAuth)
|
|
31
|
+
{ "name": "gmail", "kind": "provider", "credentialRef": "nango://google-mail", ... }
|
|
32
|
+
```
|
|
33
|
+
- `credentialRef`: a vault `ref` (→ `vault://<id>`) OR `nango://<provider>`.
|
|
34
|
+
- Tools are created **governed**.
|
|
35
|
+
- A tool's **verb catalog is DERIVED** from the skills whose `requires` names that tool — you don't list verbs on the tool.
|
|
36
|
+
|
|
37
|
+
## skills
|
|
38
|
+
|
|
39
|
+
```jsonc
|
|
40
|
+
{ "name": "draft-outreach", "kind": "instruction", "scope": "pod",
|
|
41
|
+
"description": "…", "requires": ["unipile_linkedin"],
|
|
42
|
+
"code": "# Markdown body injected into the agent's prompt …" }
|
|
43
|
+
|
|
44
|
+
{ "name": "{{name}} fetch-and-propose", "kind": "code", "scope": "pod",
|
|
45
|
+
"requires": ["generic_api"], "executionMode": "async", "timeoutSeconds": 60,
|
|
46
|
+
"parameters": { "path": "string?" },
|
|
47
|
+
"code": "// JS statement body run in the IS isolate …" }
|
|
48
|
+
```
|
|
49
|
+
- `kind`: `instruction` (prompt text in `code`) | `code` (JS, born `approved:false`) | `provider` (declarative `providerSpec` HTTP, in-process Tier-1).
|
|
50
|
+
- `requires`: the tool names the skill feeds into — this is what derives the tool's verb catalog and wires `member_of` links.
|
|
51
|
+
- code skills: `propose.entity({ profileSlug, title, properties })` requires `title` (not `name`) and routes through `checkPermissionOrPropose`. `callProvider(toolName, method, path, body?)` is POSITIONAL; the dispatcher resolves the tool's credential server-side.
|
|
52
|
+
|
|
53
|
+
## playbooks
|
|
54
|
+
|
|
55
|
+
The `playbooks[]` array holds full playbook definitions (see the `authoring-playbooks` skill). They are materialized LAST and **REQUIRE a `workspaceId`** at apply time — that is why a capability bundling playbooks is seeded `workspaceScoped: true`.
|
|
56
|
+
|
|
57
|
+
## automations (optional)
|
|
58
|
+
|
|
59
|
+
The `automations[]` array can carry WHEN→THEN flows in the same `{ name, triggerType, status, triggerConfig, flowDefinition, metadata }` shape used by `synap-backend/templates/automations/*.automation.json` (see `authoring-automations`).
|
|
60
|
+
|
|
61
|
+
## Reference templates (in the same directory)
|
|
62
|
+
|
|
63
|
+
| Template | Shape | Clone it for |
|
|
64
|
+
|---|---|---|
|
|
65
|
+
| `nango-google.capability.json` | Nango/OAuth, empty vault | Any OAuth connector |
|
|
66
|
+
| `cal-com.capability.json` | vault/API-key | A keyed HTTP service |
|
|
67
|
+
| `generic-apikey.capability.json` | vault + one api tool + one code skill | The blueprint for a new vault connector |
|
|
68
|
+
| `agency-skills.capability.json` | instruction-only skills + 2 playbooks | A know-how + process pack |
|
|
69
|
+
|
|
70
|
+
Builtin `web_fetch` / `web_search` need no template — they are always available to agents.
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: authoring-playbooks
|
|
3
|
+
description: Authors a Synap Playbook — the session-template process object that turns a goal into ordered stages over a subject entity. Use whenever the user asks to create a playbook, build a process, design a workflow with stages, set up a "process for X", add or reorder stages, or define what an agent session should do step by step (e.g. "build me a client-onboarding process", "make a 3-stage research playbook", "add a review stage").
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Authoring Playbooks
|
|
7
|
+
|
|
8
|
+
A **Playbook** is the process object in Synap: a reusable template for an AI working session. It declares a goal, the parameters that specialize it, the capabilities it is allowed to use, where it runs, what it should produce, and — first-class now — the **ordered stages** a subject moves through. When a playbook runs it instantiates a `focus_session` over a single **subject** entity, advancing one stage at a time.
|
|
9
|
+
|
|
10
|
+
This skill teaches the data model, the live authoring path, the field reference, and the run lifecycle. Read `reference/stages-contract.md` before writing stages, and `reference/worked-example.md` for a full example.
|
|
11
|
+
|
|
12
|
+
## The mental model (memorize this)
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
automation (WHEN, the trigger)
|
|
16
|
+
└─> playbook_run (a process template, instantiated)
|
|
17
|
+
└─> over a SUBJECT entity (subjectProfile resolves which one)
|
|
18
|
+
└─> in a focus_session (the runtime instance)
|
|
19
|
+
└─> currentStage = the one active stage key
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
- A playbook is a **template**. A `focus_session` is a **running instance** of it.
|
|
23
|
+
- A subject is in **exactly ONE stage at a time** — `focus_sessions.currentStage` holds the active stage key.
|
|
24
|
+
- An **automation** decides WHEN a playbook runs (its `flowAutomationId` wires the trigger). The playbook decides WHAT happens once running.
|
|
25
|
+
- The session works **over a subject**: one `company`, one `deal`, one `person`, etc. — resolved through `subjectProfile`.
|
|
26
|
+
|
|
27
|
+
## The LIVE authoring path (where playbooks actually ship)
|
|
28
|
+
|
|
29
|
+
A playbook is **not** authored as a standalone file. It ships **inside a CapabilityDefinition's `playbooks[]` array**:
|
|
30
|
+
|
|
31
|
+
1. Define it in the capability template: `synap-control-plane-api/src/seeds/capability-templates/<key>.capability.json`, under `"playbooks": [ ... ]`.
|
|
32
|
+
2. It is materialized by `createCapabilityFromDefinition()` when the capability is applied via `POST /api/hub/capabilities/apply`. Playbooks REQUIRE a `workspaceId` at apply time.
|
|
33
|
+
3. The Discord bridge seeds it by adding the capability key to `AGENCY_CAPABILITY_PLAN` in `synap-cli/src/commands/bridge-setup.ts` with `workspaceScoped: true` (the flag that tells the bridge this capability bundles playbooks, so it must be applied with a workspace).
|
|
34
|
+
|
|
35
|
+
**GOTCHA — do not copy the vestigial file.** `synap-control-plane-api/templates/packs/deep-research.playbook.json` looks like a standalone playbook template but it is VESTIGIAL: its playbook-specific fields are dropped during materialization. Never copy it or treat it as the schema. The authoritative shape is the `playbooks[]` entry inside a `.capability.json`. For a real example **with ordered stages**, see `stellar-grant-client.capability.json` and `reference/worked-example.md` (note: `agency-skills.capability.json` bundles playbooks but their `stages` are `[]`, so it does not demo the stages contract).
|
|
36
|
+
|
|
37
|
+
## Playbook field reference
|
|
38
|
+
|
|
39
|
+
| Field | Type / shape | Meaning |
|
|
40
|
+
|---|---|---|
|
|
41
|
+
| `name` | string | Display name. |
|
|
42
|
+
| `description` | string | What this process does and when it runs. |
|
|
43
|
+
| `goalTemplate` | string with `@{arg:…}` grammar | The session's objective. Interpolate params with `@{arg:paramName}`. |
|
|
44
|
+
| `params` | `{ name, label?, type, required?, description? }[]` | Inputs that specialize a run. `type`: `text` \| `number` \| `entity` \| `choice` \| `boolean`. |
|
|
45
|
+
| `inputStrategy` | `{ kind, description? }` | What the session iterates over. `kind`: `none` \| `static` \| `rotating` \| `query`. |
|
|
46
|
+
| `channelSpec` | `{ type, aiReactionMode? }` | Where it runs. `type`: `GROUP` \| `AGENT_COLLAB` \| `THREAD`. |
|
|
47
|
+
| `expectedOutputs` | `{ kind, label }[]` | The deliverables a run should produce (drives the output checklist). `kind` is **loosely typed** — stick to the shared vocab `note` \| `document` \| `report` for consistency, though any string is accepted. |
|
|
48
|
+
| `schedule` | `{ cron, enabled }` \| `null` | Optional recurring schedule. |
|
|
49
|
+
| `executor` | enum | `is-agent` \| `external-agent` \| `hybrid` — who runs the session. |
|
|
50
|
+
| `subjectProfile` | `{ profileSlug, filter? }` | The profile of the subject entity the session operates over. |
|
|
51
|
+
| `flowAutomationId` | id | The automation whose trigger fires this playbook (the WHEN). **Set post-create by a separate mutation — NOT settable via the template.** |
|
|
52
|
+
| `stages` | `PlaybookStage[]` (ordered) | The ordered process steps. See `reference/stages-contract.md`. |
|
|
53
|
+
| `grants` | `CapabilityRef[]` (stage-level only) | Advisory capability hints surfaced to the agent. See below. |
|
|
54
|
+
|
|
55
|
+
### grants — advisory capability hints (NOT enforcement)
|
|
56
|
+
|
|
57
|
+
A `grant` is a `CapabilityRef`: `{ kind, id }` where `kind` is `tool` \| `skill` \| `command` and `id` names the capability. Two things to know before you rely on them:
|
|
58
|
+
|
|
59
|
+
- **Top-level playbook `grants` are DROPPED.** They are not part of `PlaybookDefSchema` / playbook create, so a `grants` array at the playbook level is silently ignored during materialization. Declare grants on **stages** instead.
|
|
60
|
+
- **Stage `grants` are stored as opaque JSON and are currently ADVISORY.** They are surfaced to the agent at runtime via `RunContext` (the is-agent executor lists a stage's grants in the kickoff prompt) but are **NOT resolved into enforcement `capability` / `link` rows** — nothing blocks the agent from using an ungranted capability, and nothing auto-wires a granted one. Hard enforcement is a documented FOLLOW-UP, not current behavior.
|
|
61
|
+
|
|
62
|
+
Because of this, "granting" a skill at a stage really means **telling the agent to use that skill at that stage**. An `instruction` skill (e.g. `stellar-scf-grants-advisor`) is already available to the agent through the pod skill catalog + `load_skill` REGARDLESS of any grant — listing it in a stage's `grants` just points the agent at it as the stage's working methodology. Builtin `web_fetch` / `web_search` are always available and need no grant.
|
|
63
|
+
|
|
64
|
+
## The STAGES contract (the new first-class field)
|
|
65
|
+
|
|
66
|
+
Stages are **ordered** and drive the session's progression. Read `reference/stages-contract.md` for the full schema and event semantics. In brief:
|
|
67
|
+
|
|
68
|
+
```jsonc
|
|
69
|
+
"stages": [
|
|
70
|
+
{
|
|
71
|
+
"key": "scope", // stable id, referenced by currentStage
|
|
72
|
+
"name": "Scope",
|
|
73
|
+
"description": "Understand the client and their problem.",
|
|
74
|
+
"goal": "Produce a one-paragraph problem statement.", // optional
|
|
75
|
+
"grants": [{ "kind": "skill", "id": "client-brief" }], // optional, advisory hint (not enforced)
|
|
76
|
+
"expectedOutputs": [{ "kind": "note", "label": "Problem statement" }],
|
|
77
|
+
"suggestedTasks": ["Read the intake form", "List open questions"]
|
|
78
|
+
}
|
|
79
|
+
]
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
- The running session tracks `focus_sessions.currentStage` (the active stage key).
|
|
83
|
+
- Changing `currentStage` emits a **`focus_session.stage_changed`** event — automations can trigger on it (e.g. notify when a subject reaches "build").
|
|
84
|
+
- **Empty `stages`** = legacy progress-only behavior (a single 0→100% bar, no stage events).
|
|
85
|
+
|
|
86
|
+
## Run lifecycle
|
|
87
|
+
|
|
88
|
+
1. **Start** — `playbooks.run` (tRPC) or `synap_start_session`. Instantiates a `focus_session` over the resolved subject, `currentStage` = first stage key.
|
|
89
|
+
2. **Advance** — `synap_update_session`: set `currentStage` to move stages (emits `stage_changed`), update `progress`, `addOutput` / `completeOutput` as deliverables land.
|
|
90
|
+
3. **Complete** — `synap_complete_session` when the goal is met.
|
|
91
|
+
|
|
92
|
+
## Authoring checklist
|
|
93
|
+
|
|
94
|
+
1. State the **goal** as a `goalTemplate` with `@{arg:…}` for anything parameterized.
|
|
95
|
+
2. Define **params** (minimum needed to specialize a run).
|
|
96
|
+
3. Pick the **subjectProfile** — what single entity is each run about?
|
|
97
|
+
4. Write **ordered stages** — each with a clear `goal` and `expectedOutputs`. One subject, one active stage.
|
|
98
|
+
5. Declare stage **grants** to point the agent at the skills/tools each stage should use (advisory hints, not an access gate; put them on stages, not the playbook level).
|
|
99
|
+
6. Set **channelSpec**, **executor**, and (optionally) **schedule**.
|
|
100
|
+
7. Place it in the capability template's `playbooks[]` and add the key to `AGENCY_CAPABILITY_PLAN` (`workspaceScoped: true`).
|
|
101
|
+
|
|
102
|
+
See `reference/worked-example.md` for a complete 3-stage client-process playbook over a `company` subject.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# PlaybookStage — the stages contract
|
|
2
|
+
|
|
3
|
+
Stages are the first-class, ordered process steps of a playbook. They replaced the old "progress percentage only" model. A subject moving through a playbook is in **exactly one stage at a time**.
|
|
4
|
+
|
|
5
|
+
## Schema
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
type PlaybookStage = {
|
|
9
|
+
key: string; // stable identifier; what currentStage holds. Required.
|
|
10
|
+
name: string; // human label. Required.
|
|
11
|
+
description?: string; // what this stage is about
|
|
12
|
+
goal?: string; // the concrete objective of this stage
|
|
13
|
+
grants?: CapabilityRef[]; // advisory capability hints ({ kind: tool|skill|command, id }) — see note below
|
|
14
|
+
expectedOutputs?: ExpectedOutput[];// deliverables expected before advancing ({ kind, label }; kind loosely typed)
|
|
15
|
+
suggestedTasks?: string[]; // soft checklist the agent can turn into tasks
|
|
16
|
+
};
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
- `key` is **stable** — `focus_sessions.currentStage` stores it, and `stage_changed` events carry it. Don't rename keys on a live playbook; add/deprecate instead.
|
|
20
|
+
- Stages are **ordered** by their position in the `stages[]` array.
|
|
21
|
+
- `grants` here are **advisory**: stored as opaque JSON and surfaced to the agent in the stage's kickoff prompt via `RunContext`, but NOT resolved into enforcement `capability` / `link` rows (hard enforcement is a documented follow-up). "Granting" a skill at a stage = telling the agent to use it there; the skill is already reachable via the pod skill catalog + `load_skill` regardless. Declare grants on stages, not at the playbook level — top-level playbook `grants` are dropped during materialization.
|
|
22
|
+
|
|
23
|
+
## Runtime semantics
|
|
24
|
+
|
|
25
|
+
- A `focus_session` starts with `currentStage` = the first stage's `key`.
|
|
26
|
+
- Calling `synap_update_session` with a new `currentStage` advances (or moves back) the subject.
|
|
27
|
+
- **Every change to `currentStage` emits a `focus_session.stage_changed` event.** Automations can subscribe with an event trigger on `focus_session.stage_changed.*` (optionally filtered by the new stage key) — this is how "when a deal reaches negotiation, notify the team" is wired.
|
|
28
|
+
- **Empty `stages` array = legacy behavior**: the session tracks only a 0→100% `progress` value and emits no stage events.
|
|
29
|
+
|
|
30
|
+
## Design rules
|
|
31
|
+
|
|
32
|
+
- Keep stages **few and meaningful** (3–6 is typical). Each stage should represent a real change in what the agent is doing or waiting on.
|
|
33
|
+
- Give every stage a `goal` and at least one `expectedOutput` so "done with this stage" is observable.
|
|
34
|
+
- Use `suggestedTasks` for the soft checklist; use `expectedOutputs` for the hard deliverables that gate advancement. For `expectedOutputs[].kind`, keep to the shared (loosely typed) vocab `note` | `document` | `report`.
|
|
35
|
+
- Stage `grants` point the agent at the right capability per stage — name the LinkedIn tool in the "outreach" stage, not the "scope" stage. Remember they are advisory hints, not an access gate.
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Worked example — a 3-stage client-process playbook
|
|
2
|
+
|
|
3
|
+
Goal: a reusable process that takes a prospective `company`, scopes their problem, abstracts it into a buildable spec, and ships a first build. The subject is one `company` per run. Three ordered stages: **Scope → Abstract → Build**.
|
|
4
|
+
|
|
5
|
+
This is a `playbooks[]` entry inside a `.capability.json` (NOT a standalone file).
|
|
6
|
+
|
|
7
|
+
```jsonc
|
|
8
|
+
{
|
|
9
|
+
"name": "Client Build Process",
|
|
10
|
+
"description": "Take a prospective company from raw problem to a shipped first build, one stage at a time.",
|
|
11
|
+
"goalTemplate": "Run @{arg:companyName} through scope → abstract → build. Produce a problem statement, a buildable spec, and a working first deliverable. Every write stays proposal-gated.",
|
|
12
|
+
"params": [
|
|
13
|
+
{ "name": "companyName", "label": "Company", "type": "entity", "required": true,
|
|
14
|
+
"description": "The company this run is about (the subject)." }
|
|
15
|
+
],
|
|
16
|
+
"subjectProfile": { "profileSlug": "company" },
|
|
17
|
+
"inputStrategy": { "kind": "none" },
|
|
18
|
+
"channelSpec": { "type": "AGENT_COLLAB", "aiReactionMode": "only_mentioned" },
|
|
19
|
+
"executor": "is-agent",
|
|
20
|
+
"schedule": null,
|
|
21
|
+
"expectedOutputs": [
|
|
22
|
+
{ "kind": "note", "label": "Problem statement" },
|
|
23
|
+
{ "kind": "document", "label": "Buildable spec" },
|
|
24
|
+
{ "kind": "document", "label": "First build deliverable" }
|
|
25
|
+
],
|
|
26
|
+
"stages": [
|
|
27
|
+
{
|
|
28
|
+
"key": "scope",
|
|
29
|
+
"name": "Scope",
|
|
30
|
+
"description": "Understand the company and the problem worth solving.",
|
|
31
|
+
"goal": "Produce a one-paragraph problem statement grounded in the company context.",
|
|
32
|
+
"grants": [{ "kind": "skill", "id": "client-brief" }],
|
|
33
|
+
"expectedOutputs": [{ "kind": "note", "label": "Problem statement" }],
|
|
34
|
+
"suggestedTasks": ["Assemble the client brief", "List the open questions", "Confirm the problem with the operator"]
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"key": "abstract",
|
|
38
|
+
"name": "Abstract",
|
|
39
|
+
"description": "Turn the problem into a buildable specification.",
|
|
40
|
+
"goal": "Write a spec: scope, constraints, success criteria, and the smallest first deliverable.",
|
|
41
|
+
"expectedOutputs": [{ "kind": "document", "label": "Buildable spec" }],
|
|
42
|
+
"suggestedTasks": ["Draft the spec", "Define success criteria", "Get spec sign-off"]
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"key": "build",
|
|
46
|
+
"name": "Build",
|
|
47
|
+
"description": "Ship the first deliverable against the spec.",
|
|
48
|
+
"goal": "Produce a working first build and link it to the company.",
|
|
49
|
+
"grants": [{ "kind": "tool", "id": "gdrive" }],
|
|
50
|
+
"expectedOutputs": [{ "kind": "document", "label": "First build deliverable" }],
|
|
51
|
+
"suggestedTasks": ["Build the first deliverable", "Link it to the company", "Hand off for review"]
|
|
52
|
+
}
|
|
53
|
+
]
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## How a run flows
|
|
58
|
+
|
|
59
|
+
1. Operator (or an automation via `flowAutomationId`) starts the playbook with `companyName` = a specific company. The `focus_session` opens with `currentStage = "scope"`.
|
|
60
|
+
2. The agent works the **scope** stage, producing the problem-statement note. When done, `synap_update_session({ currentStage: "abstract" })` advances it — emitting `focus_session.stage_changed` (new stage `abstract`).
|
|
61
|
+
3. An automation could trigger on `focus_session.stage_changed.*` filtered to `build` to post "X has reached the build stage" in the team channel.
|
|
62
|
+
4. When the build deliverable lands and is linked, `synap_complete_session` closes the session.
|
|
63
|
+
|
|
64
|
+
Note on `grants`: declare them on **stages**, not at the playbook level — top-level playbook `grants` are dropped during materialization. Stage `grants` are **advisory** (surfaced to the agent in the stage kickoff prompt, not resolved into enforcement rows — see the SKILL.md grants section). Keep the surface tight — only point at `gdrive` in the build stage where it is actually used, so the agent knows that is the stage's tool.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: bookmark-enrichment
|
|
3
|
+
description: Enriches a bookmark entity from the page it points to — reads the URL, extracts title + description, classifies it, and links it into the CRM graph. Runs automatically when a bookmark is created.
|
|
4
|
+
metadata:
|
|
5
|
+
synap_native: true
|
|
6
|
+
auto_load: false
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
You are a bookmark enrichment agent. You receive a single bookmark entity id (`entityId`) for a bookmark that was just created from a URL found in a channel.
|
|
10
|
+
|
|
11
|
+
Do this:
|
|
12
|
+
|
|
13
|
+
1. **Read the bookmark** to get its `url` property.
|
|
14
|
+
2. **Fetch the page** at that URL and read its content (the `<title>`, the meta description, and the first ~500 words of body text).
|
|
15
|
+
3. **Classify** the link into exactly one category: `website`, `pitch-deck`, `document`, `tool`, `article`, or `other`.
|
|
16
|
+
4. **Update the bookmark entity**: set its `title` to the page title and its `description` to a one or two sentence summary. Store the category in a `category` property.
|
|
17
|
+
5. **Promote when it's more than a bookmark**:
|
|
18
|
+
- If the URL is the **company website** of the client this bookmark is linked to, update that company entity's `website` property.
|
|
19
|
+
- If it is a **pitch deck** or a substantial **document**, create a `document` entity for it and link it to the client.
|
|
20
|
+
|
|
21
|
+
Be precise and quiet: enrich the bookmark, link what should be linked, and stop. Do not create duplicates — check the linked client + company first. Discord/CDN/social-media noise URLs (already filtered upstream) should not reach you; if one does, leave it minimally enriched.
|
|
22
|
+
|
|
23
|
+
## Surface + pin (significant links only)
|
|
24
|
+
|
|
25
|
+
Only do this section if the bookmark's `category` is `pitch-deck`, `document`, or `website`. Skip for `tool`, `article`, or `other` — keep the channel signal-high.
|
|
26
|
+
|
|
27
|
+
The bookmark carries `sourceChannelId` (the Discord channel the URL was posted in) and `sourceMessageId` (the message that contained the URL).
|
|
28
|
+
|
|
29
|
+
**Firewall rule (non-negotiable): NEVER post or pin in a `client-comms` channel.** Those channels mirror to the client's Telegram — the client must not see bot activity. All bot feedback goes to the client's `team` channel only.
|
|
30
|
+
|
|
31
|
+
Steps:
|
|
32
|
+
1. Look up the client entity linked to this bookmark. List its channels and identify:
|
|
33
|
+
- the `team` channel (`branchPurpose = 'team'`, internal)
|
|
34
|
+
- the `client-comms` channel (`branchPurpose = 'client-comms'`, mirrored to Telegram)
|
|
35
|
+
2. Determine where the source message came from by matching `sourceChannelId`:
|
|
36
|
+
- **Source is `client-comms`**: do NOT post or pin there. Post a short notice in the `team` channel containing (a) a link to the source message so the team can jump to context, and (b) the bookmark entity deep-link `synap://open/entity/<entityId>`. Pinning is optional in this case.
|
|
37
|
+
- **Source is the `team` channel**: it's internal — pin the source message via `pin_channel_message(sourceChannelId, sourceMessageId)` and reply in-place with the entity deep-link `synap://open/entity/<entityId>`.
|
|
38
|
+
3. If you cannot resolve the client or its channels, skip silently — do not error.
|
|
39
|
+
|
|
40
|
+
Entity deep-link format: `synap://open/entity/<entityId>` (opens the bookmark in the Synap browser app).
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: coordinating-agents
|
|
3
|
+
description: Spawns, queries, and consolidates sub-agents working in parallel. Use when work splits into independent parts that benefit from concurrent agents.
|
|
4
|
+
metadata:
|
|
5
|
+
synap_native: true
|
|
6
|
+
auto_load: false
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
Coordinate with other agents: spawn, query, consolidate. Know when to work alone vs in parallel.
|
|
10
|
+
|
|
11
|
+
## COORDINATING PARALLEL WORK
|
|
12
|
+
|
|
13
|
+
**Default behaviour:** For any task requiring 2+ steps or multiple perspectives (research, analysis, planning, comparison, design), **always** use `dispatch_agent(mode='parallel')` to create visible work streams. The user sees these as branches on their timeline — showing progress in real-time is better than a single long response that takes minutes to appear.
|
|
14
|
+
|
|
15
|
+
When delegating via `dispatch_agent`, choose the right mode:
|
|
16
|
+
- **ephemeral** — inline sub-agent, no UI trace. Use ONLY for trivial single-step lookups (a quick search, one fact check)
|
|
17
|
+
- **parallel** — creates a visible branch the user can interact with. **This is the preferred mode.** Use for anything requiring multiple tool calls or distinct angles of investigation
|
|
18
|
+
- **deliberate** — A2A structured critique session (specialist ↔ orchestrator) before returning a result. Use for high-stakes, hard-to-reverse decisions where adversarial reasoning improves quality
|
|
19
|
+
|
|
20
|
+
**When to branch (non-exhaustive examples):**
|
|
21
|
+
- Competitive analysis → dispatch 2–3 parallel researchers (one per competitor or angle)
|
|
22
|
+
- Architecture design → dispatch a CTO persona for technical feasibility + a PM persona for requirements
|
|
23
|
+
- Project planning → dispatch parallel task breakdown + risk analysis + timeline estimation
|
|
24
|
+
- Content creation → dispatch research branch + outline branch, then consolidate
|
|
25
|
+
- Decision making → dispatch pros branch + cons branch + alternatives branch
|
|
26
|
+
|
|
27
|
+
**Parallel research pattern:**
|
|
28
|
+
1. Dispatch 2–3 parallel branches for different angles of the same question
|
|
29
|
+
2. On the next message (or after reading with `query_agent`), call `consolidate_branches`
|
|
30
|
+
3. Deliver one coherent synthesis, noting which branches contributed
|
|
31
|
+
|
|
32
|
+
**Rule of thumb:** If you're about to make 3+ sequential tool calls to answer a question, consider whether those calls represent distinct perspectives that could run in parallel branches instead. Branches make your thinking visible and let the user follow along.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: coordinating-branches
|
|
3
|
+
description: Spins off parallel work as branches and consolidates their results. Use when a task has heavy side-work, needs a deep research dive, would bloat the main channel, or benefits from delegation.
|
|
4
|
+
metadata:
|
|
5
|
+
synap_native: true
|
|
6
|
+
auto_load: false
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
Use branches for parallel work: create_branch, query results, consolidate. Understand tree position.
|
|
10
|
+
|
|
11
|
+
## BRANCH NETWORK
|
|
12
|
+
When your context includes a **Branch Network** section, it maps your position in the thread tree:
|
|
13
|
+
- **Parallel branches** — other specialist agents working on related tasks from the same parent
|
|
14
|
+
- **Child branches** — branches you have previously spawned
|
|
15
|
+
|
|
16
|
+
**The user sees your branch network as a visual timeline.** Every branch you create appears on it with its name and purpose as visible labels. Use this as a communication tool — write clear, descriptive `branchPurpose` strings that tell the user what each branch is investigating (e.g., "Analyzing competitor pricing models" not "research").
|
|
17
|
+
|
|
18
|
+
**Reading and using the network:**
|
|
19
|
+
- Use `query_agent(branchChannelId, "question")` to read findings from any branch — read-only, no side effects
|
|
20
|
+
- Use `consolidate_branches([id1, id2, ...], "synthesize into...")` when branches have completed work — merges outputs into one coherent response
|
|
21
|
+
- Check sibling branches before responding — they may have already found what the user needs
|
|
22
|
+
|
|
23
|
+
**When to consolidate:**
|
|
24
|
+
- The user asks for a summary or final answer after parallel work was dispatched
|
|
25
|
+
- Multiple child branches appear in the Branch Network
|
|
26
|
+
- After parallel branches complete, **always** call `consolidate_branches` to synthesize findings back to the main thread — the user expects a summary, not silence
|
|
27
|
+
- Never leave parallel work unresolved — always synthesize and surface findings
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mapping-the-server
|
|
3
|
+
description: Understands a Discord server's structure (categories, channels, members) and proposes ONE reviewable CRM graph — clients, partners, companies, people, channel bindings, and the relations between them — for the operator to accept in a single move. The ambient "make sense of my server" onboarding.
|
|
4
|
+
metadata:
|
|
5
|
+
synap_native: true
|
|
6
|
+
auto_load: false
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
You are the server-mapping agent. The operator pointed you at their Discord server and wants you to **understand it and propose the whole CRM graph in one move** — so they can review it, accept it, and watch everything link up. Your job is to make them feel *understood*: nothing important left out, sensible structure, theirs to approve.
|
|
10
|
+
|
|
11
|
+
You receive the server structure as input: `categories` (each with its `channels`), `members`, and optionally recent channel activity. You also have read access to the pod.
|
|
12
|
+
|
|
13
|
+
## 1. Orient before proposing
|
|
14
|
+
- Call `list_profiles` / `orient` to learn which entity types exist (e.g. `client`, `partner`, `company`, `person`, `contact`) and read the bento schema so you propose entities with the RIGHT profile + properties.
|
|
15
|
+
- Look at what's **already in the pod**. Never propose a duplicate of an entity or binding that already exists — match by name/domain first and *link to the existing one* instead.
|
|
16
|
+
|
|
17
|
+
## 2. Read the structure — COMPANY-FIRST
|
|
18
|
+
- **A category is usually a "room" for ONE organization** (a client or a partner). Its name is your strongest signal.
|
|
19
|
+
- **The model is company-first:** every client/partner organization is a **`company`** entity. The client/partner is a SEPARATE entity that is **linked to** that company — so the pod can list all companies, all clients, and all partners independently. A single company can be BOTH a client and a partner.
|
|
20
|
+
- **Channel firewall role:** `client-comms` / `tg-*` / `comms` / a mirrored external chat → `branchPurpose: 'client-comms'` (mirrored to the client — internal-only!). `team` / `internal` / `notes` → `branchPurpose: 'team'`.
|
|
21
|
+
- **TEAM THREADS (forums):** the input has a `forums[]` array of forum POSTS (threads) — these are usually the INTERNAL **team** thread for each client (e.g. an "important" forum with one thread per client). A client almost always has TWO surfaces: a mirrored comms channel (`tg-acme`, `client-comms`) AND a team thread (`acme`, `team`). **PAIR them by name** (`tg-acme` ↔ forum thread `acme`) and bind BOTH to the SAME client/company entity — the comms channel as `client-comms`, the team thread as `team`. This pairing is what lets digests + notices land in the team thread and NEVER the client channel.
|
|
22
|
+
- **People → contacts:** each channel carries a `participants` list — the recent message senders. For a client channel these are the **mirrored Telegram people** (the company's real contacts), not Discord members. Non-team participants become **`contact`** entities linked to that room's company.
|
|
23
|
+
- **Skip generic channels** (`general`, `welcome`, `help`, `rules`, voice).
|
|
24
|
+
|
|
25
|
+
## 3. Build ONE proposed graph — company-first chain
|
|
26
|
+
Call `propose_entity_graph` ONCE. For EACH organization (room), build this chain:
|
|
27
|
+
1. **`company`** entity (ref e.g. `acme-co`) — the organization itself. Reuse an existing company via `existingEntityId` (match by name) instead of duplicating.
|
|
28
|
+
2. **`client`** or **`partner`** entity (ref e.g. `acme-client`) — the relationship — and a relation linking it to the company: `{ sourceRef: "acme-client", targetRef: "acme-co", type: "belongs_to" }`.
|
|
29
|
+
3. **`contact`** entities for each non-team `participant` in the room's channels, each linked to the company: `{ sourceRef: "<contactRef>", targetRef: "acme-co", type: "works_at" }`.
|
|
30
|
+
4. **Team members** (your own people) → **`person`** entities (NOT `contact` — the bridge's `/link-client --assigned` dedup looks up team members in the `person` profile only; using `contact` would create duplicates). Reuse existing. Add an `{ sourceRef: "<personRef>", targetRef: "acme-client", type: "assigned_to" }` relation when a team member clearly owns the room.
|
|
31
|
+
5. **`bindings`**: each real channel → the company's `entityRef`, with `branchPurpose` (`client-comms` for the mirrored channel, `team` for the internal one). When a client has BOTH a comms channel and a paired forum team thread, emit TWO bindings to the same `entityRef` — one `client-comms`, one `team` — so the firewall has a safe place (the team thread) to surface digests.
|
|
32
|
+
|
|
33
|
+
So per org the graph is: **`contact → company ← client/partner`**, with channels bound and firewall roles set. Propose ALL orgs as **one** `propose_entity_graph` call — never dozens of single proposals.
|
|
34
|
+
|
|
35
|
+
(Missing `team` threads — rooms with a `client-comms` channel but no `team` channel — note them in your summary. After the graph is accepted, ensure the sibling team channel for each such client with `channel.ensure({ contextObjectType: 'entity', contextObjectId: <clientEntityId>, branchPurpose: 'team' })` so `channel.resolve(channelType: 'team')` has a firewall-safe target for digests + review flags. See the `routing-to-channels` skill for the full bind/ensure lifecycle.)
|
|
36
|
+
|
|
37
|
+
## 4. The firewall is absolute
|
|
38
|
+
NEVER propose a write, binding, post, or thread that would put bot/team activity into a `client-comms` channel — those mirror to the client. All collaboration lands in `team` channels/threads. When in doubt about a channel's role, propose it as `client-comms` (the safe default) and say so.
|
|
39
|
+
|
|
40
|
+
## 5. Be conservative + honest
|
|
41
|
+
- Only propose what the structure supports. Mark low-confidence inferences explicitly ("likely a partner — confirm?").
|
|
42
|
+
- If a room is ambiguous (is it a client, a partner, or a topic channel?), include your best guess but flag it for the operator's review rather than guessing silently.
|
|
43
|
+
- Do not delete or rename anything. You only ever ADD structure as a proposal.
|
|
44
|
+
|
|
45
|
+
## 6. Close with reassurance, not a data dump
|
|
46
|
+
Return a short, human summary that makes the operator feel covered:
|
|
47
|
+
- What you found: "**Q companies → N clients, M partners, P contacts** across your rooms."
|
|
48
|
+
- The shape: a few highlights ("**Acme** → company + client, 3 contacts, comms + team channels bound").
|
|
49
|
+
- **Show bindings with channel mentions** so the operator can verify what maps to what — write each bound channel as `<#CHANNELID>` (Discord renders these as clickable channel links), e.g. "Acme → `<#123…>` (client-comms), `<#456…>` (team)".
|
|
50
|
+
- Anything you flagged for their judgment.
|
|
51
|
+
- **The review link:** pass the link from the tool's result through **verbatim** — do NOT rewrite it into document/cell syntax like `[[open:side|…]]` (that's plain text in Discord and can't be clicked). Keep it exactly as the tool returned it.
|
|
52
|
+
- **The next step:** end by telling them that once they accept the graph, they can run **`/digest-all`** to pull the contacts, notes and links out of each channel's existing history (the channels are only bound on accept, so this is the moment to backfill them).
|
|
53
|
+
|
|
54
|
+
You are the support layer that already gets it. Map the server, propose the graph, hand them one confident decision.
|