@zibby/skills 2.0.4 → 2.0.5
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/index.js +1 -1
- package/dist/jira.d.ts +26 -1
- package/dist/jira.js +8 -8
- package/dist/package.json +4 -4
- package/dist/trackers/index.js +1 -1
- package/dist/trackers/jira-adapter.js +5 -5
- package/docs/templates/catalog-metadata.md +101 -0
- package/docs/templates/composition.md +97 -0
- package/docs/templates/deploy-time-config.md +228 -0
- package/docs/templates/index.md +138 -0
- package/docs/templates/models.md +157 -0
- package/docs/templates/node-declarations.md +149 -0
- package/docs/templates/remote-mcp.md +105 -0
- package/docs/templates/requires.md +183 -0
- package/docs/templates/sidecars.md +163 -0
- package/docs/templates/stores.md +113 -0
- package/docs/templates/surfaces.md +184 -0
- package/docs/templates/update-behavior.md +108 -0
- package/package.json +4 -4
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
---
|
|
2
|
+
sidebar_position: 11
|
|
3
|
+
title: Catalog metadata
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Catalog metadata
|
|
7
|
+
|
|
8
|
+
Everything here reaches the **card**. Most of it is presentation, and most of it
|
|
9
|
+
is deliberately excluded from the update signal, so improving your copy never
|
|
10
|
+
pops an "Update available" badge on somebody's deployed agent for nothing.
|
|
11
|
+
|
|
12
|
+
## Identity and presentation
|
|
13
|
+
|
|
14
|
+
| Name | Type | Required | Allowed values | Default | Update behavior |
|
|
15
|
+
|---|---|---|---|---|---|
|
|
16
|
+
| `slug` | string | **Yes** | the agent's identity — the folder name, the deploy route, the row of everybody who already installed it | — | **Never change it** |
|
|
17
|
+
| `tagline` | string | No | one clamped line — on the detail card this *is* the header | `''` | Card only |
|
|
18
|
+
| `tags` | string[] | No | catalog sections; the card is grouped by the first one in section order | `[]` | Card only |
|
|
19
|
+
| `browseRank` | number | No | lower sorts first; no rank sorts last | none | Card only |
|
|
20
|
+
| `capabilities` | string[] | No | around five bullets, each one thing, each starting with a verb | `[]` | Card only |
|
|
21
|
+
| `conversationStarters` | string[] | No | example prompts | `[]` | Card only |
|
|
22
|
+
| `icon` | string | No | `./icon.png` beside your graph, or an `https://` URL | the Zibby mark | Card only |
|
|
23
|
+
| `iconPrompt` / `iconBackground` | string | No | inputs to the offline icon generator | none | Card only |
|
|
24
|
+
| `releaseNotes` | string | No | markdown — see below | `''` | Card only |
|
|
25
|
+
| `defaultSlug` | string | No | pre-fills the "Deploy as" field | the slug | Seeded once |
|
|
26
|
+
|
|
27
|
+
:::tip Tagline vs description
|
|
28
|
+
The detail card reads **tagline first**; the browse cards and the featured hero
|
|
29
|
+
read **description first**. So keep the tagline to a few words and let the
|
|
30
|
+
description be two real sentences. They are not interchangeable.
|
|
31
|
+
:::
|
|
32
|
+
|
|
33
|
+
## Behaviour and availability
|
|
34
|
+
|
|
35
|
+
| Name | Type | Required | Allowed values | Default | Update behavior |
|
|
36
|
+
|---|---|---|---|---|---|
|
|
37
|
+
| `maxRuntimeMinutes` | number | No | clamped to the platform window; the default is 25 and the ceiling 60 | none | **Seeded once** — a number you set on the Settings tab survives every Update |
|
|
38
|
+
| `selfHostOnly` | boolean | No | `true` when the agent needs a service container | `false` | Re-applied |
|
|
39
|
+
| `hidden` | boolean | No | `true` keeps the card out of browse while remaining installable by slug | `false` | Re-applied |
|
|
40
|
+
| `kind` | string | No | `fleet`, `app` — see [Composition](./composition.md) | none | Re-applied |
|
|
41
|
+
| `deps` | object | No | extra runtime dependencies the agent needs beyond `@zibby/core` | `{}` | **Frozen at deploy** |
|
|
42
|
+
|
|
43
|
+
### `maxRuntimeMinutes` — measure it, don't guess
|
|
44
|
+
|
|
45
|
+
Declare it when you actually know your agent's cost. One shipped agent measured
|
|
46
|
+
a first pass at 24 minutes 53 seconds against a 25-minute default, which made
|
|
47
|
+
its repair pass unreachable on every fresh install — so it declares 60. Another
|
|
48
|
+
declares 30 because a cap that is too *low* gets the container killed between
|
|
49
|
+
two steps and strands work.
|
|
50
|
+
|
|
51
|
+
A cap that is too low is worse than one that is too high.
|
|
52
|
+
|
|
53
|
+
### `selfHostOnly` means exactly one thing
|
|
54
|
+
|
|
55
|
+
**"This agent needs a service container."** It does not mean "absent from the
|
|
56
|
+
cloud": the card still ships to the cloud catalog so its documentation stays
|
|
57
|
+
readable everywhere. Only the deploy is refused, and the refusal says why.
|
|
58
|
+
|
|
59
|
+
## Release notes
|
|
60
|
+
|
|
61
|
+
`releaseNotes` is what the "Update available" dialog shows somebody who already
|
|
62
|
+
runs your agent. It is **mandatory for any user-visible change**, and it is
|
|
63
|
+
short.
|
|
64
|
+
|
|
65
|
+
1. **This version only.** One line per change.
|
|
66
|
+
2. **The outcome, not the mechanism.** What is different for them, in their
|
|
67
|
+
words — not what you refactored.
|
|
68
|
+
3. **Do not accumulate history.** Drop the previous version's notes rather than
|
|
69
|
+
prepending to them.
|
|
70
|
+
4. **Ten short lines at most.**
|
|
71
|
+
|
|
72
|
+
Good:
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
Answering the team's question is now just replying, once, like a person.
|
|
76
|
+
• Reply in your own words — any wording, any language.
|
|
77
|
+
• Answer on one ticket of a plan and it counts for the whole plan.
|
|
78
|
+
• You no longer touch labels.
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Bad: a changelog going back to the initial release, or a paragraph about which
|
|
82
|
+
module was rewritten.
|
|
83
|
+
|
|
84
|
+
No notes at all gives the user *"No release notes provided by the author"*.
|
|
85
|
+
|
|
86
|
+
## Gotchas
|
|
87
|
+
|
|
88
|
+
**`hidden` and `selfHostOnly` are different axes.** `hidden` is visibility;
|
|
89
|
+
`selfHostOnly` is a real constraint. A card can be one, the other, or both.
|
|
90
|
+
|
|
91
|
+
**A `kind` the platform does not recognise is dropped.** The section you meant
|
|
92
|
+
to appear in simply never appears — check the allowed values.
|
|
93
|
+
|
|
94
|
+
**Your `spec` block lives outside your template directory**, so a
|
|
95
|
+
metadata-only change moves no source file. The platform tracks it separately, so
|
|
96
|
+
your edit still reaches the card — see [Update behavior](./update-behavior.md).
|
|
97
|
+
|
|
98
|
+
## See also
|
|
99
|
+
|
|
100
|
+
- [Update behavior](./update-behavior.md)
|
|
101
|
+
- [The declaration model](./index.md)
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
---
|
|
2
|
+
sidebar_position: 5
|
|
3
|
+
title: Composition & fleets
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Composition — `dispatchesWorkflow` and `kind`
|
|
7
|
+
|
|
8
|
+
## What it is
|
|
9
|
+
|
|
10
|
+
An agent can run **another** catalog agent as a sub-graph. Deploying the parent
|
|
11
|
+
cascades: every declared member is installed as the parent's own child, bound to
|
|
12
|
+
it, and recorded on its row — so one Deploy gives you a whole team.
|
|
13
|
+
|
|
14
|
+
## Syntax — three forms
|
|
15
|
+
|
|
16
|
+
**1. The declarative sub-graph node.** The engine records the member for you:
|
|
17
|
+
|
|
18
|
+
```js
|
|
19
|
+
graph.addNode('build', {
|
|
20
|
+
workflow: 'frontend-specialist',
|
|
21
|
+
input: (state) => ({ ticket: state.ticket }),
|
|
22
|
+
output: (result) => ({ pr: result.prUrl }),
|
|
23
|
+
});
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
**2. A single member on a custom node:**
|
|
27
|
+
|
|
28
|
+
```js
|
|
29
|
+
export const poPlanNode = {
|
|
30
|
+
name: 'plan',
|
|
31
|
+
dispatchesWorkflow: 'product-owner',
|
|
32
|
+
execute: async (state, ctx) => { /* … */ },
|
|
33
|
+
};
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
**3. A roster — one node fanning out over many members:**
|
|
37
|
+
|
|
38
|
+
```js
|
|
39
|
+
export const dispatchNode = {
|
|
40
|
+
name: 'dispatch',
|
|
41
|
+
dispatchesWorkflow: ['ticket-triage', 'developer', 'frontend-specialist',
|
|
42
|
+
'gitlab-code-review', 'generate-test-cases', 'product-owner'],
|
|
43
|
+
execute: async (state, ctx) => { /* dispatches whichever the manager chose */ },
|
|
44
|
+
};
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Properties
|
|
48
|
+
|
|
49
|
+
| Name | Where | Type | Required | Allowed values | Default | Update behavior |
|
|
50
|
+
|---|---|---|---|---|---|---|
|
|
51
|
+
| `dispatchesWorkflow` | node | string \| string[] | No | catalog slugs | absent | Re-applied — a new member is installed on the next deploy |
|
|
52
|
+
| `kind` | `spec` | string | No | `fleet`, `app` | none | `fleet` is card-only; `app` changes the deploy path |
|
|
53
|
+
| `composedOf` | — | — | **derived, never declared** | — | — | Re-applied |
|
|
54
|
+
|
|
55
|
+
`kind: 'fleet'` moves the card into the Fleet section of the catalog and lets it
|
|
56
|
+
say "installs a team of N" *before* you install it. It does **not** change how
|
|
57
|
+
the agent deploys.
|
|
58
|
+
|
|
59
|
+
`kind: 'app'` is different in kind: the card is a hosted application you open in
|
|
60
|
+
a browser, not an agent, and it deploys down a different path.
|
|
61
|
+
|
|
62
|
+
## What deploy does
|
|
63
|
+
|
|
64
|
+
1. Builds one ordered member list — sub-graph children first, then anything
|
|
65
|
+
named by [`requires`](./requires.md).
|
|
66
|
+
2. Installs each member (recursively), in parallel.
|
|
67
|
+
3. Records the bindings on the parent, so a dispatch at run time resolves to the
|
|
68
|
+
right instance.
|
|
69
|
+
4. Records the member names on the parent's row for the Agents list.
|
|
70
|
+
|
|
71
|
+
If any member fails, **the whole deploy fails** and the rows this deploy created
|
|
72
|
+
are rolled back. You never end up with half a fleet.
|
|
73
|
+
|
|
74
|
+
## Gotchas
|
|
75
|
+
|
|
76
|
+
**A member can be a string or an array — always handle both.** A roster node
|
|
77
|
+
declares many members on one node; reading only the string form installs one and
|
|
78
|
+
leaves every other dispatch failing at run time.
|
|
79
|
+
|
|
80
|
+
**An agent cannot dispatch an ancestor.** A cycle is refused at deploy.
|
|
81
|
+
|
|
82
|
+
**A dispatch node runs no model of its own** and is excluded from "apply this
|
|
83
|
+
model to every node".
|
|
84
|
+
|
|
85
|
+
**A parent collects its children's model keys.** If your child runs a different
|
|
86
|
+
vendor, the deploy asks for that key too — and marks it non-blocking, so a
|
|
87
|
+
branch you will not use never stops the install.
|
|
88
|
+
|
|
89
|
+
**A member that subscribes to events is suppressed while it is a member.**
|
|
90
|
+
Otherwise one pull request would fire both the fleet (which runs the member
|
|
91
|
+
in-process) and the standalone member — a double review. Deploy the member
|
|
92
|
+
on its own and it starts responding to events again.
|
|
93
|
+
|
|
94
|
+
## See also
|
|
95
|
+
|
|
96
|
+
- [`requires`](./requires.md) — the other kind of member.
|
|
97
|
+
- [Deploy-time configuration](./deploy-time-config.md) — event subscriptions.
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
---
|
|
2
|
+
sidebar_position: 9
|
|
3
|
+
title: Deploy-time configuration
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Deploy-time configuration
|
|
7
|
+
|
|
8
|
+
Four declarations that shape what happens **when somebody installs your agent**:
|
|
9
|
+
what they are asked, what is seeded for them, and what starts a run.
|
|
10
|
+
|
|
11
|
+
| Block | Writes to | Asked at |
|
|
12
|
+
|---|---|---|
|
|
13
|
+
| [`selections`](#selections) | the agent's Env bag — **configuration** | deploy |
|
|
14
|
+
| [`deployInput`](#deployinput) | the agent's default trigger payload | deploy |
|
|
15
|
+
| [`defaultSchedule`](#defaultschedule) | the agent's schedules | deploy (once) |
|
|
16
|
+
| [`workflow.json` → `triggers`](#triggers) | the agent's trigger settings | every deploy |
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## `selections`
|
|
21
|
+
|
|
22
|
+
### What it is
|
|
23
|
+
|
|
24
|
+
A value the operator must **pick from a live list some integration owns** —
|
|
25
|
+
which board this agent works, which space it writes to — rather than dig an id
|
|
26
|
+
out of a URL and type it into an environment variable.
|
|
27
|
+
|
|
28
|
+
One declaration renders a dropdown of the real options the connected system
|
|
29
|
+
returns, and the answer lands in the agent's encrypted Env bag.
|
|
30
|
+
|
|
31
|
+
### Syntax
|
|
32
|
+
|
|
33
|
+
```js
|
|
34
|
+
spec: {
|
|
35
|
+
selections: [{
|
|
36
|
+
id: 'board',
|
|
37
|
+
label: 'Board',
|
|
38
|
+
from: 'board_tracker', // a provider, or a one-of group
|
|
39
|
+
providerKey: 'BOARD_TRACKER', // records WHICH provider was chosen
|
|
40
|
+
keys: {
|
|
41
|
+
vikunja: 'BOARD_VIKUNJA_PROJECT_ID',
|
|
42
|
+
jira: 'BOARD_JIRA_PROJECT_KEY',
|
|
43
|
+
},
|
|
44
|
+
required: true,
|
|
45
|
+
help: 'The board this agent polls for tickets marked ready.',
|
|
46
|
+
}],
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Properties
|
|
51
|
+
|
|
52
|
+
| Name | Type | Required | Allowed values | Default | Update behavior |
|
|
53
|
+
|---|---|---|---|---|---|
|
|
54
|
+
| `id` | string | **Yes** | lowercase, starts with a letter, ≤ 41 chars, unique in the array | — | Seeded once |
|
|
55
|
+
| `label` | string | **Yes** | non-empty — it is what the picker is called | — | Card only |
|
|
56
|
+
| `from` | string | **Yes** | a provider id, or a one-of group the platform already knows | — | Seeded once |
|
|
57
|
+
| `keys` | object | **Yes** | `{ provider: 'ENV_KEY' }` — every provider must belong to `from` | — | Seeded once |
|
|
58
|
+
| `providerKey` | string | **Yes** when the group offers more than one provider | a writable Env key | none | Seeded once |
|
|
59
|
+
| `required` | boolean | No | | `true` | Seeded once |
|
|
60
|
+
| `help` | string | No | | none | Card only |
|
|
61
|
+
|
|
62
|
+
### Why `keys` is a map
|
|
63
|
+
|
|
64
|
+
The value written is a different *kind* of thing per provider: Vikunja addresses
|
|
65
|
+
a board by a numeric project id, Jira by a project key (`"PROJ"`). One
|
|
66
|
+
environment variable cannot express that, and collapsing them would leave the
|
|
67
|
+
reader guessing which system's id it holds.
|
|
68
|
+
|
|
69
|
+
### Gotchas
|
|
70
|
+
|
|
71
|
+
**A one-of group with more than one option needs a `providerKey`.** A choice
|
|
72
|
+
that records nothing deploys an agent that cannot tell which system it was
|
|
73
|
+
pointed at — so the declaration is refused.
|
|
74
|
+
|
|
75
|
+
**A provider with no key in `keys` is simply not offered.** That is legitimate:
|
|
76
|
+
some systems are reached another way and have no list to show.
|
|
77
|
+
|
|
78
|
+
**It is seeded once.** A value you have already set survives every Update, and
|
|
79
|
+
the deploy tells you what it kept.
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## `deployInput`
|
|
84
|
+
|
|
85
|
+
### What it is
|
|
86
|
+
|
|
87
|
+
A field of your agent's input schema, annotated so the deploy asks for it once
|
|
88
|
+
and stores it as the agent's default trigger payload.
|
|
89
|
+
|
|
90
|
+
### Syntax
|
|
91
|
+
|
|
92
|
+
```js
|
|
93
|
+
// state.js
|
|
94
|
+
repoUrl: z.string().url()
|
|
95
|
+
.meta({ deployInput: {
|
|
96
|
+
required: true,
|
|
97
|
+
source: 'github-repo',
|
|
98
|
+
label: 'GitHub repo',
|
|
99
|
+
help: 'Pick the repository whose flaky tests this agent should fix.',
|
|
100
|
+
}}),
|
|
101
|
+
|
|
102
|
+
circleProjectSlug: z.string().optional()
|
|
103
|
+
.meta({ deployInput: {
|
|
104
|
+
source: 'circleci-project',
|
|
105
|
+
deriveFrom: 'repoUrl', // resolved automatically, never typed
|
|
106
|
+
label: 'CircleCI project',
|
|
107
|
+
}}),
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Properties
|
|
111
|
+
|
|
112
|
+
| Name | Type | Required | Allowed values | Default | Update behavior |
|
|
113
|
+
|---|---|---|---|---|---|
|
|
114
|
+
| `required` | boolean | No | gates the deploy in the dashboard, the CLI **and** over MCP | `false` | Seeded once |
|
|
115
|
+
| `source` | string | No | which control renders it, or which resolver fills it | none | Seeded once |
|
|
116
|
+
| `deriveFrom` | string | No | another field's name — auto-resolved, never user-entered, never required of the user | none | Seeded once |
|
|
117
|
+
| `label` / `help` | string | No | | the field name | Card only |
|
|
118
|
+
|
|
119
|
+
### Gotchas
|
|
120
|
+
|
|
121
|
+
`deployInput.required` is the **deploy gate**, which is separate from whether
|
|
122
|
+
the field is optional in your schema.
|
|
123
|
+
|
|
124
|
+
Use `selections` instead when the value is agent *configuration* your code reads
|
|
125
|
+
from the environment — not part of a run's input.
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## `defaultSchedule`
|
|
130
|
+
|
|
131
|
+
### What it is
|
|
132
|
+
|
|
133
|
+
A cron-driven agent does nothing until something wakes it. `defaultSchedule` is
|
|
134
|
+
the floor: deploy installs it as the agent's ordinary schedule **when the agent
|
|
135
|
+
has no schedule at all**.
|
|
136
|
+
|
|
137
|
+
### Syntax
|
|
138
|
+
|
|
139
|
+
```js
|
|
140
|
+
spec: {
|
|
141
|
+
defaultSchedule: { cron: '*/15 * * * *', name: 'Board tick' },
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### Properties
|
|
146
|
+
|
|
147
|
+
| Name | Type | Required | Allowed values | Default | Update behavior |
|
|
148
|
+
|---|---|---|---|---|---|
|
|
149
|
+
| `cron` | string | **Yes** | a **5-field** Unix cron (`m h dom mon dow`) | — | Seeded once |
|
|
150
|
+
| `timezone` | string | No | an IANA zone | `UTC` | Seeded once |
|
|
151
|
+
| `name` | string | No | | none | Seeded once |
|
|
152
|
+
| `input` | object | No | the trigger body | `{}` | Seeded once |
|
|
153
|
+
|
|
154
|
+
A one-shot date is refused — a template cannot know a date.
|
|
155
|
+
|
|
156
|
+
### Gotchas
|
|
157
|
+
|
|
158
|
+
**Any existing entry blocks the seed.** One you created, the seeded one after
|
|
159
|
+
you edited it, a paused one (pausing is a disable, not a delete), even a
|
|
160
|
+
one-shot that already fired. So an Update can never resurrect a schedule you
|
|
161
|
+
paused, and never re-points one you changed.
|
|
162
|
+
|
|
163
|
+
**One entry, not an array.** The declaration is a floor, and a floor is one
|
|
164
|
+
cadence. An agent that needs several schedules has an operator who set them, and
|
|
165
|
+
seed-once means those are never touched.
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## `triggers`
|
|
170
|
+
|
|
171
|
+
### What it is
|
|
172
|
+
|
|
173
|
+
An optional `workflow.json` beside your graph, declaring how runs start. It is
|
|
174
|
+
re-applied on **every** deploy, including an Update.
|
|
175
|
+
|
|
176
|
+
### Syntax
|
|
177
|
+
|
|
178
|
+
```json
|
|
179
|
+
{ "triggers": { "events": ["github.pr.opened", "github.pr.updated"] } }
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
```json
|
|
183
|
+
{ "triggers": { "api": true } }
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### Properties
|
|
187
|
+
|
|
188
|
+
| Name | Type | Required | Allowed values | Default | Update behavior |
|
|
189
|
+
|---|---|---|---|---|---|
|
|
190
|
+
| `api` | boolean | No | `true` ships the inbound webhook on by default | off (opt-in) | Re-applied |
|
|
191
|
+
| `events` | string[] | No | `github.pr.opened`, `github.pr.updated`, `github.pr.commented`, `github.pr.mentioned`, and the `gitlab.mr.*` equivalents | `[]` | Re-applied |
|
|
192
|
+
|
|
193
|
+
Inbound webhooks are routed **by subscription, not by agent name**: a delivery is
|
|
194
|
+
normalised to an event, the repository is resolved to a project, and every
|
|
195
|
+
subscribed agent gets its own independent run.
|
|
196
|
+
|
|
197
|
+
### Gotchas
|
|
198
|
+
|
|
199
|
+
**A member of a fleet is suppressed from event routing while it is a member.**
|
|
200
|
+
Otherwise one pull request fires both the fleet — which runs the member itself —
|
|
201
|
+
and the standalone member, giving you two reviews. Deploy the member on its own
|
|
202
|
+
and it starts responding again.
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
## Sample trigger bodies
|
|
207
|
+
|
|
208
|
+
Two card-only fields that make the Trigger dialog usable:
|
|
209
|
+
|
|
210
|
+
```js
|
|
211
|
+
spec: {
|
|
212
|
+
triggerExample: { ticketKey: 'PROJ-123' },
|
|
213
|
+
triggerExamples: [
|
|
214
|
+
{ label: 'board tick', body: '{}' },
|
|
215
|
+
{ label: 'one ticket', body: '{"ticketKey":"PROJ-123"}' },
|
|
216
|
+
{ label: 'plan from a PRD', body: '{"prd":"# Feature\\n\\nAs a user I want …"}' },
|
|
217
|
+
],
|
|
218
|
+
}
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
`triggerExample` pre-fills the editable body. `triggerExamples` renders one
|
|
222
|
+
click-to-use reference per source below it. Both must be **valid JSON** — JSON
|
|
223
|
+
has no comments.
|
|
224
|
+
|
|
225
|
+
## See also
|
|
226
|
+
|
|
227
|
+
- [Update behavior](./update-behavior.md)
|
|
228
|
+
- [Composition](./composition.md)
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
---
|
|
2
|
+
sidebar_position: 1
|
|
3
|
+
title: The declaration model
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Agent templates — the declaration model
|
|
7
|
+
|
|
8
|
+
An **agent template** is the source of a reusable agent: its graph, its state
|
|
9
|
+
schema, and a **declaration block** that says what the platform must do when
|
|
10
|
+
somebody installs it.
|
|
11
|
+
|
|
12
|
+
If you have written CloudFormation, you already know the shape:
|
|
13
|
+
|
|
14
|
+
| CloudFormation | Zibby |
|
|
15
|
+
|---|---|
|
|
16
|
+
| stack template | the template |
|
|
17
|
+
| `Resources` | the declaration blocks (`models`, `stores`, `requires`, …) |
|
|
18
|
+
| `create-stack` | deploying the template from the catalog |
|
|
19
|
+
| `Ref` / logical names | a declared **name** the platform binds at deploy |
|
|
20
|
+
| *Update requires: Replacement* | fields frozen at deploy — see [Update behavior](./update-behavior.md) |
|
|
21
|
+
|
|
22
|
+
The rule the whole system is built around:
|
|
23
|
+
|
|
24
|
+
> **Adding a new agent means writing only a declaration.** No new UI branch, no
|
|
25
|
+
> new gate, no code that knows this agent's name.
|
|
26
|
+
|
|
27
|
+
Everything the platform does for your agent — which model keys it asks you for,
|
|
28
|
+
which stores it provisions, which service containers it pulls, which endpoints
|
|
29
|
+
it publishes, which other agents it installs alongside — is computed from the
|
|
30
|
+
declaration. One renderer, one provisioner, one deploy path, for every agent
|
|
31
|
+
that exists or ever will.
|
|
32
|
+
|
|
33
|
+
## Where a declaration lives
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
my-agent/
|
|
37
|
+
├── graph.mjs ← the graph; NODES carry their own declarations
|
|
38
|
+
├── state.js ← the input schema; fields can carry deploy-time annotations
|
|
39
|
+
├── workflow.json ← optional: which events start a run
|
|
40
|
+
├── package.json ← the versions this agent will be FROZEN at
|
|
41
|
+
└── icon.png ← optional
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
plus the **`spec` block** that declares everything else:
|
|
45
|
+
|
|
46
|
+
```js
|
|
47
|
+
spec: {
|
|
48
|
+
slug: 'my-agent',
|
|
49
|
+
tagline: 'One clamped line that IS the card header.',
|
|
50
|
+
tags: ['Coding'],
|
|
51
|
+
capabilities: [
|
|
52
|
+
'Each bullet is one thing, starting with a verb',
|
|
53
|
+
],
|
|
54
|
+
models: [ /* … */ ],
|
|
55
|
+
surfaces: ['cli', 'webhook', 'schedule', 'mcp'],
|
|
56
|
+
releaseNotes: 'What changed in THIS version.',
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
A template with no `spec` block is not in the catalog at all. It is still
|
|
61
|
+
usable as a local scaffold, but nothing syncs, nothing renders, nothing deploys.
|
|
62
|
+
|
|
63
|
+
:::note `marketplace:` is the same block
|
|
64
|
+
Older templates spell this block `marketplace:`. That spelling still works and
|
|
65
|
+
always will — `spec:` is simply the neutral name for the same thing. You never
|
|
66
|
+
need to rename an existing template.
|
|
67
|
+
:::
|
|
68
|
+
|
|
69
|
+
## What happens at deploy
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
your declaration
|
|
73
|
+
│
|
|
74
|
+
▼
|
|
75
|
+
┌────────────────────┐
|
|
76
|
+
│ the catalog card │ models → credential slots
|
|
77
|
+
└────────────────────┘ surfaces → which sections the page shows
|
|
78
|
+
│ requires → "installs a team of N"
|
|
79
|
+
▼
|
|
80
|
+
you press Deploy
|
|
81
|
+
│
|
|
82
|
+
┌───────────┼───────────┬──────────────┬─────────────┐
|
|
83
|
+
▼ ▼ ▼ ▼ ▼
|
|
84
|
+
stores sidecars member remote MCP selections
|
|
85
|
+
created pulled + agents servers written to
|
|
86
|
+
+ bound verified installed bound the Env bag
|
|
87
|
+
+ started + attached
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Every step is idempotent. Deploying the same version twice changes nothing;
|
|
91
|
+
deploying a newer version re-runs the steps and keeps what you configured by
|
|
92
|
+
hand.
|
|
93
|
+
|
|
94
|
+
## Backward compatibility by synthesis
|
|
95
|
+
|
|
96
|
+
A block you do not declare is not "missing" — the platform **synthesises the
|
|
97
|
+
equivalent**, so an old template behaves exactly as it always did:
|
|
98
|
+
|
|
99
|
+
- no `models` → one ordinary bring-your-own-key model block;
|
|
100
|
+
- no `surfaces` → the four standard channels (CLI, webhook, schedule, MCP);
|
|
101
|
+
- no `entryPoints` → the platform serves each surface itself.
|
|
102
|
+
|
|
103
|
+
:::tip Empty is not the same as absent
|
|
104
|
+
`models: []` is a **real declaration**: "this agent runs no model at all". The
|
|
105
|
+
deploy will not ask you for an AI key. Leaving `models` out entirely means
|
|
106
|
+
something different — "give me the normal one".
|
|
107
|
+
:::
|
|
108
|
+
|
|
109
|
+
## Names, not addresses
|
|
110
|
+
|
|
111
|
+
No template ever writes down a concrete id, host or URL. It declares a **name**;
|
|
112
|
+
the platform binds that name to a real resource at deploy; and whatever consumes
|
|
113
|
+
it resolves the name late — differently on the cloud and on your own box.
|
|
114
|
+
|
|
115
|
+
That is why the same template works in both places, and why nothing breaks when
|
|
116
|
+
a resource is re-created.
|
|
117
|
+
|
|
118
|
+
:::danger Never put a credential in a declaration
|
|
119
|
+
A declaration is public data that travels with the card. Tokens, keys and
|
|
120
|
+
passwords reach an agent **only** through its encrypted Env bag — never through
|
|
121
|
+
a template, a prompt, a trigger payload or a chat message.
|
|
122
|
+
:::
|
|
123
|
+
|
|
124
|
+
## The blocks
|
|
125
|
+
|
|
126
|
+
| Block | What it declares |
|
|
127
|
+
|---|---|
|
|
128
|
+
| [`models`](./models.md) | which model(s) the agent runs, and who supplies the key |
|
|
129
|
+
| [`stores`](./stores.md) | durable storage, provisioned at deploy and injected by name |
|
|
130
|
+
| [`requires`](./requires.md) | an endpoint another agent publishes, installed and attached for you |
|
|
131
|
+
| [`dispatchesWorkflow` / `kind`](./composition.md) | other agents this one runs as sub-graphs — a fleet |
|
|
132
|
+
| [`surfaces` / `entryPoints`](./surfaces.md) | which channels the agent offers, and where each one lives |
|
|
133
|
+
| [`sidecars` / `sidecarSpecs`](./sidecars.md) | a long-lived service container the agent needs |
|
|
134
|
+
| [`remoteMcp`](./remote-mcp.md) | a hosted third-party MCP server the agent is for |
|
|
135
|
+
| [deploy-time configuration](./deploy-time-config.md) | pickers, inputs, a default schedule, trigger events |
|
|
136
|
+
| [node declarations](./node-declarations.md) | skills, integrations and vendor pins, per node |
|
|
137
|
+
| [catalog metadata](./catalog-metadata.md) | slug, tagline, tags, release notes, availability |
|
|
138
|
+
| [Update behavior](./update-behavior.md) | what changes on re-deploy, what is seeded once, what is frozen |
|