@agent-compose/cli 0.2.1 → 0.3.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.
@@ -7,131 +7,362 @@ effort: high
7
7
 
8
8
  # Generate Workflow
9
9
 
10
- Interactively scaffold a new workflow from a plain-English description.
11
-
12
- > **Mental model.** A workflow is `async (ctx, sandbox) => T`. The `ctx`
13
- > exposes `run`, `input?`, `setMetadata`, and `step` (for named timeline
14
- > phases). The `sandbox` is the runner's own VM — pass it to
15
- > `agent({ sandbox, ... })` and to any helper that takes a
16
- > `SandboxProvider`. Agent loops live *inside* the workflow body via
17
- > `agent`. There's no `defineAgent` / `spawnAgent` model anymore.
18
-
19
- ## Steps
20
-
21
- 1. Ask the user:
22
- - What should this workflow do? (plain English describe the phases,
23
- their inputs/outputs, and any external calls.)
24
- - Workflow name? (kebab-case, e.g. `code-review`)
25
- - Where to create it? (project-relative path, e.g. `src/workflows/`)
26
- - Runtime for agent loops? (default `claudeRuntime`)
27
- - Network policy needed? (which domains + which brokered secrets to inject?)
28
- - Capture a snapshot on success? (default off; on for setup/environment
29
- workflows whose end-state other workflows boot from)
30
- - Boot this run from another workflow's snapshot? (default no — fresh
31
- `node24` base sandbox)
32
- - Enable the built-in memory extractor? (default off — opt in only when
33
- this workflow's events are worth memorising AND the `workflow-memory`
34
- template is registered in the same factory)
35
- - Additional post-hooks? (ordered list of workflow names that fan out
36
- after this run completes)
37
-
38
- 2. If the user has a reference workflow in their project, read it to match
39
- their conventions (prompt structure, error handling). Otherwise follow
40
- the patterns in [`sdk/README.md`](../../sdk/README.md) and the example
41
- in [`docs/how-it-works.md`](../../docs/how-it-works.md).
42
-
43
- 3. Generate a complete, real implementation:
44
-
45
- ```ts
46
- import { defineWorkflow, agent, claudeRuntime } from "@agent-compose/sdk";
47
- import PROMPT from "./prompt.md" with { type: "text" };
48
-
49
- export default defineWorkflow({
50
- async run(ctx, sandbox) {
51
- // Phase 1 wrap any non-agent setup in ctx.step() so it shows
52
- // up on the timeline with its own duration:
53
- const data = await ctx.step("fetch-input", async () => {
54
- // pure-server work, fetches, etc.
55
- });
56
-
57
- // Phase 2 — agent loop. Each `agent` is one iteration cycle
58
- // with its own prompt + tool allowlist + budget.
59
- const result = await agent({
60
- sandbox,
61
- runtime: claudeRuntime,
62
- prompt: `${PROMPT}\n\nContext: ${JSON.stringify(data)}`,
63
- tools: ["Read", "Write", "Edit", "Bash", "Grep", "Glob"],
64
- budget: { turnsPerIteration: 40, maxIterations: 6 },
65
- // responseSchema: MyZodSchema, // for typed handoffs
66
- });
67
-
68
- await ctx.setMetadata({ summary: result.status?.summary });
69
- return { ok: !!result.status?.completed };
70
- },
71
-
72
- // ── Optional metadata picked up by the bundler at registration ──
73
- //
74
- // networkPolicy / placeholders — outbound traffic + brokered secrets:
75
- //
76
- // networkPolicy: {
77
- // allow: {
78
- // "api.github.com": [{ transform: [{ headers: {
79
- // Authorization: "basic:$GITHUB_TOKEN",
80
- // } }] }],
81
- // "*.openai.com": [{ transform: [{ headers: {
82
- // "OpenAI-Beta": "$OPENAI_BETA_HEADER",
83
- // } }] }],
84
- // },
85
- // },
86
- // // Placeholder values the runner sees in env vars AFTER brokering.
87
- // // The real secret never enters the VM — Vercel's firewall
88
- // // substitutes it on the way out. Only needed when a tool /
89
- // // SDK validates the env-var format on startup.
90
- // placeholders: { GITHUB_TOKEN: "ghp_" + "x".repeat(36) },
91
- //
92
- // snapshots all snapshot config in one object:
93
- //
94
- // snapshots: {
95
- // // Boot from a specific captured snapshot. Pick the id from
96
- // // `agentc snapshot list` or the factory snapshots page.
97
- // bootFrom: { snapshotId: "snap_abc…" },
98
- // saveLatest: true, // capture sandbox on success
99
- // retainSteps: false, // keep one snapshot per successful step
100
- // },
101
- //
102
- // memory — opt-in (default false). Requires `workflow-memory` to
103
- // be registered in this factory.
104
- // memory: true,
105
- //
106
- // postRunHooks ordered list of workflow names that run after this:
107
- // postRunHooks: ["audit-trail", "notify-slack"],
108
- });
109
- ```
110
-
111
- - Always declare the return type (or let TS infer + show it on hover).
112
- - Use `Promise.all` to fan out independent `agent` calls.
113
- - Use `ctx.step("phase-name", () => …)` for any named non-agent phase.
114
-
115
- 4. Show the complete file plus a separate `prompt.md` (or per-phase
116
- prompts) and confirm before writing.
117
-
118
- 5. Write the files, then suggest the user run `bun run typecheck` (or
119
- their project's equivalent) to validate.
120
-
121
- 6. Tell the user: `agentc register <path>` to register, then
122
- `agentc invoke <name> --follow` to test.
10
+ Walk the user through building a new workflow, **in their own words**.
11
+ This skill is used by operators and product folks as well as engineers
12
+ ask questions in plain language and decide the shape internally.
13
+
14
+ ## What to ask the user
15
+
16
+ Ask these one at a time. Keep the language non-technical. Don't ask
17
+ about "step-form vs run-form" that's an internal call.
18
+
19
+ 1. **What should this workflow do?**
20
+ One paragraph in plain English. This becomes the workflow's
21
+ `description` (shown on the dashboard tile and run page header).
22
+ Example: "Pulls open pull requests from a GitHub repo, scores each
23
+ one by review urgency, and posts the top five to Slack."
24
+
25
+ 2. **What information does it take in?**
26
+ Walk through each input field: a short name, a type (text, number,
27
+ yes/no, list, object), and a one-line description of what it's for.
28
+ Each field's description becomes a `.describe(...)` on the zod
29
+ schema so it shows up in the dashboard's Input panel.
30
+
31
+ 3. **What does it produce?**
32
+ Same pattern for the output. Fields + types + per-field
33
+ descriptions. The dashboard's Output panel renders these straight
34
+ from the schema.
35
+
36
+ 4. **Where should it live?**
37
+ Project-relative path, e.g. `src/workflows/`. Also ask for a
38
+ kebab-case name if one isn't obvious from the description.
39
+
40
+ 5. **Does it need to call external services?**
41
+ If yes, ask which (GitHub, Slack, OpenAI, an internal API, etc.).
42
+ You'll generate a network policy + brokered-secret stubs.
43
+
44
+ 6. **Should it run on a schedule?**
45
+ If yes, ask for the cadence in plain English ("every weekday at 9am
46
+ ET", "every hour", "the 1st of every month"). Convert to cron
47
+ yourself (UTC). Schedules are *separate from workflow source*: you
48
+ don't put cron in `defineWorkflow(...)`. After register, run
49
+ `agentc schedule create <name> --workflow <wf> --cron '<expr>'`
50
+ (or, for the simple "one cron per workflow" case, pass
51
+ `--schedule '<expr>'` to `agentc register` and the CLI auto-creates
52
+ a same-named schedule). Read the cron expression back to the user
53
+ to confirm.
54
+
55
+ 7. **Anything else worth recording?**
56
+ Optional. Most workflows are fine without this.
57
+
58
+ **Do NOT ask** the user about:
59
+
60
+ - step-form vs run-form
61
+ - sandbox environments / dependency installation
62
+ - snapshots: `saveLatest`, `retainSteps`, `bootFrom`
63
+ - `memory` / `postRunHooks` / `processors`
64
+
65
+ Decide those internally based on what they described (see the
66
+ "Internal decisions" section below).
67
+
68
+ ## Internal decisions
69
+
70
+ After answering the questions above, decide the shape WITHOUT asking:
71
+
72
+ ### Pick the workflow shape
73
+
74
+ - **Step-form** (`defineWorkflow({...}).step(s1).step(s2).build()` with
75
+ `defineStep(...)` objects) — pick this when the body decomposes
76
+ cleanly into named phases with typed handoffs. Each step's output
77
+ threads into the next step's input. The dashboard renders each step
78
+ as a typed phase with its own duration. Examples: ETL pipelines,
79
+ classification → enrichment → publish, fetch → score → rank.
80
+
81
+ - **Run-form** (one `async (ctx, sandbox)` body with `agent({...})`
82
+ calls inside) — pick this when the body is dominated by one or more
83
+ agent loops. Decomposing an LLM iteration into typed engine steps is
84
+ the wrong shape. Use `ctx.step("phase-name", () => …)` inside the
85
+ body for observability sub-events when there's pre-agent setup
86
+ worth tracing on the run timeline.
87
+
88
+ When the user's description says "agent", "LLM", "the model decides",
89
+ "reasons through", "writes a summary based on", "navigates the
90
+ website" that's run-form. When they describe deterministic phases
91
+ that each transform structured data — that's step-form. If genuinely
92
+ mixed, default to run-form and use `ctx.step` for the deterministic
93
+ phases.
94
+
95
+ ### Should it have a sandbox environment?
96
+
97
+ If the workflow needs specific tools, CLIs, or installed packages in
98
+ its runner VM (Playwright + Chromium, a specific Node version, an SDK
99
+ that needs `npm install`-ing first), it needs a **sandbox
100
+ environment** to capture that pre-installed state. The user doesn't
101
+ need to know about this — you decide.
102
+
103
+ When you decide a sandbox env is needed:
104
+
105
+ 1. Generate a small `defineSandboxEnvironment` workflow alongside the
106
+ user's workflow. Name it after the deps it captures (e.g.
107
+ `playwright-env`).
108
+ 2. Register that first with `agentc register --build` so the snapshot
109
+ is captured.
110
+ 3. Reference the captured snapshot from the user's workflow via
111
+ `snapshots: { bootFrom: { snapshotId: "<id from the env's first
112
+ run>" } }`.
113
+ 4. Tell the user about it in user terms: "I'll also create a one-time
114
+ setup workflow `playwright-env` that installs Playwright. We
115
+ register that first to capture a baseline image, then your workflow
116
+ boots from that image so it doesn't reinstall on every run."
117
+
118
+ Most workflows DO NOT need this. Default to no sandbox env.
119
+
120
+ ### Always include in the generated file
121
+
122
+ - `description: "..."` on the `defineWorkflow` / `defineSandboxEnvironment`
123
+ call — straight from the user's question 1 answer.
124
+ - `.describe("...")` on **every** zod schema field — from the user's
125
+ question 2 + 3 answers. Schema descriptions appear in the dashboard
126
+ IO panels; without them, fields show only their type.
127
+ - `.describe("...")` on the root schema too where helpful — surfaces
128
+ at the panel header.
129
+
130
+ ## Templates
131
+
132
+ Generate the appropriate template based on your internal shape
133
+ decision.
134
+
135
+ ### Template A — step-form (typed pipeline)
136
+
137
+ ```ts
138
+ import { defineWorkflow, defineStep } from "@agent-compose/sdk";
139
+ import { z } from "zod";
140
+
141
+ const InputSchema = z.object({
142
+ repo: z.string().describe("GitHub repository as `owner/name`"),
143
+ limit: z.number().int().positive().describe("Maximum number of PRs to score"),
144
+ }).describe("Inputs for the PR triage workflow");
145
+
146
+ const FetchOutput = z.object({
147
+ prs: z.array(z.object({
148
+ number: z.number().describe("PR number"),
149
+ title: z.string().describe("PR title"),
150
+ author: z.string().describe("PR author's GitHub login"),
151
+ })).describe("Open PRs pulled from GitHub"),
152
+ });
153
+
154
+ const ScoreOutput = z.object({
155
+ scored: z.array(z.object({
156
+ number: z.number().describe("PR number"),
157
+ score: z.number().describe("Review-urgency score, 0..1"),
158
+ })).describe("PRs scored by review urgency"),
159
+ });
160
+
161
+ const OutputSchema = z.object({
162
+ top: z.array(z.object({
163
+ number: z.number().describe("PR number"),
164
+ score: z.number().describe("Review-urgency score, 0..1"),
165
+ })).describe("The top-scoring PRs, descending by score"),
166
+ }).describe("Top PRs surfaced by the triage workflow");
167
+
168
+ const fetchStep = defineStep({
169
+ name: "fetch-prs",
170
+ input: InputSchema,
171
+ output: FetchOutput,
172
+ run: async ({ input }) => {
173
+ // Pure server-side work: fetch, parse, transform.
174
+ return { prs: [/* ... */] };
175
+ },
176
+ });
177
+
178
+ const scoreStep = defineStep({
179
+ name: "score-prs",
180
+ input: FetchOutput,
181
+ output: ScoreOutput,
182
+ run: ({ input }) => ({
183
+ scored: input.prs.map(p => ({ number: p.number, score: 0 })),
184
+ }),
185
+ });
186
+
187
+ const pickTopStep = defineStep({
188
+ name: "pick-top",
189
+ input: ScoreOutput,
190
+ output: OutputSchema,
191
+ run: ({ input }) => ({ top: input.scored.slice(0, 5) }),
192
+ });
193
+
194
+ export default defineWorkflow({
195
+ id: "pr-triage",
196
+ description: "Pulls open PRs from a GitHub repo, scores each one by review urgency, surfaces the top five.",
197
+ input: InputSchema,
198
+ output: OutputSchema,
199
+ })
200
+ .step(fetchStep)
201
+ .step(scoreStep)
202
+ .step(pickTopStep)
203
+ .build();
204
+ ```
205
+
206
+ Notes:
207
+ - Each step's `output` schema must satisfy the next step's `input`
208
+ schema (the SDK enforces this at `defineWorkflow().step(...)` time
209
+ via TS inference). Reshape inside the upstream step's `run` body,
210
+ not at the boundary.
211
+ - Step bodies don't receive a `sandbox`. If a step needs to run code
212
+ inside the runner VM, that's the agent-driven shape — use run-form.
213
+
214
+ ### Template B — run-form (agent-driven body)
215
+
216
+ ```ts
217
+ import { defineWorkflow, agent, claudeRuntime } from "@agent-compose/sdk";
218
+ import { z } from "zod";
219
+ import PROMPT from "./prompt.md" with { type: "text" };
220
+
221
+ const InputSchema = z.object({
222
+ repo: z.string().describe("GitHub repository as `owner/name`"),
223
+ }).describe("Inputs for the code review agent");
224
+
225
+ const OutputSchema = z.object({
226
+ ok: z.boolean().describe("True when the agent finished its review"),
227
+ summary: z.string().optional().describe("One-paragraph summary of the agent's findings"),
228
+ }).describe("Result of the code review agent");
229
+
230
+ export default defineWorkflow({
231
+ description: "Runs an LLM agent that reviews recent changes in a repo and writes a summary.",
232
+ input: InputSchema,
233
+ output: OutputSchema,
234
+
235
+ async run(ctx, sandbox) {
236
+ // Pre-agent setup. `ctx.step("phase", () => ...)` is for the run
237
+ // timeline — emits step_started / step_completed events. It's
238
+ // observability sugar, not an engine step.
239
+ const data = await ctx.step("fetch-input", async () => {
240
+ // pure-server fetch / preparation
241
+ return { /* ... */ };
242
+ });
243
+
244
+ // Agent loop — the LLM iterates against the sandbox until it
245
+ // emits `exit_signal: true` or hits the budget.
246
+ const result = await agent({
247
+ sandbox,
248
+ runtime: claudeRuntime,
249
+ prompt: `${PROMPT}\n\nContext: ${JSON.stringify(data)}`,
250
+ tools: ["Read", "Write", "Edit", "Bash", "Grep", "Glob"],
251
+ budget: { turnsPerIteration: 40, maxIterations: 6 },
252
+ // responseSchema: MyZodSchema, // for typed handoffs
253
+ });
254
+
255
+ await ctx.setMetadata({ summary: result.status?.summary });
256
+ return {
257
+ ok: !!result.status?.completed,
258
+ summary: result.status?.summary,
259
+ };
260
+ },
261
+
262
+ // ── Optional metadata, attached by the bundler at registration ──
263
+ //
264
+ // networkPolicy: outbound traffic + brokered secret substitution.
265
+ // networkPolicy: {
266
+ // allow: {
267
+ // "api.github.com": [{ transform: [{ headers: {
268
+ // Authorization: "basic:$GITHUB_TOKEN",
269
+ // } }] }],
270
+ // },
271
+ // },
272
+ // // Placeholder values the runner sees in env vars AFTER brokering.
273
+ // // Only needed when a tool / SDK validates the env var format on
274
+ // // startup. The real secret never enters the VM — Vercel's
275
+ // // firewall substitutes it on the way out.
276
+ // placeholders: { GITHUB_TOKEN: "ghp_" + "x".repeat(36) },
277
+ //
278
+ // snapshots — boot source + capture mode:
279
+ // snapshots: {
280
+ // bootFrom: { snapshotId: "snap_abc…" },
281
+ // saveLatest: true,
282
+ // retainSteps: false,
283
+ // },
284
+ //
285
+ // memory — opt-in. Requires `workflow-memory` to be registered in
286
+ // this factory.
287
+ // memory: true,
288
+ //
289
+ // postRunHooks — workflows that run after this one completes:
290
+ // postRunHooks: ["audit-trail", "notify-slack"],
291
+ });
292
+ ```
293
+
294
+ Notes:
295
+ - Always declare the return type (or let TS infer + show it on hover).
296
+ - `Promise.all` to fan out independent `agent` calls.
297
+ - `ctx.step("phase-name", () => …)` for any named non-agent phase
298
+ worth showing on the dashboard timeline.
299
+
300
+ ### Sandbox environment companion (only when you decided one is needed)
301
+
302
+ ```ts
303
+ // playwright-env.ts — captures a baseline VM with Playwright pre-installed.
304
+ // Register this first with `agentc register playwright-env.ts --build`
305
+ // so the snapshot exists before user workflows reference it.
306
+ import { defineSandboxEnvironment } from "@agent-compose/sdk";
307
+
308
+ export default defineSandboxEnvironment({
309
+ name: "playwright-env",
310
+ description: "Sandbox with Playwright + Chromium installed for browser-using agents.",
311
+ setup: async (sb) => {
312
+ await sb.commands.run("sudo npm install -g playwright");
313
+ await sb.commands.run("sudo npx playwright install --with-deps chromium");
314
+ },
315
+ });
316
+ ```
317
+
318
+ After `agentc register --build` succeeds, the CLI prints a snapshot
319
+ id; reference it on the user workflow:
320
+
321
+ ```ts
322
+ export default defineWorkflow({
323
+ description: "...",
324
+ input: InputSchema,
325
+ output: OutputSchema,
326
+ snapshots: { bootFrom: { snapshotId: "<id from --build>" } },
327
+ // ...
328
+ });
329
+ ```
330
+
331
+ ## Final steps
332
+
333
+ 1. Show the user the file(s) you plan to write and confirm before
334
+ writing. In plain language: "I'll create `pr-triage.ts` in
335
+ `src/workflows/`. It takes `{ repo, limit }` and returns
336
+ `{ top: [...] }`. Sound right?"
337
+ 2. Write the files.
338
+ 3. Suggest `bun run typecheck` (or the project's equivalent) to
339
+ validate.
340
+ 4. Tell the user the next commands in plain English:
341
+ - "To register: `agentc register src/workflows/pr-triage.ts`."
342
+ - "To test it: `agentc invoke pr-triage --follow`."
343
+ - (If you added a sandbox env companion: "First register the
344
+ `playwright-env` workflow with `--build` so the snapshot is
345
+ captured, then register and invoke `pr-triage`.")
346
+ - (If the user asked for a schedule at step 6:
347
+ "To run it on the schedule: `agentc schedule create pr-triage-daily
348
+ --workflow pr-triage --cron '<expr>'` — the cron pattern we
349
+ worked out earlier.")
123
350
 
124
351
  ## When the user asks for memory extraction
125
352
 
126
- The built-in memory extractor (`workflow-memory`) is a separate workflow
127
- that must be registered in the same factory. Walk them through it:
353
+ The built-in memory extractor (`workflow-memory`) is a separate
354
+ workflow that must be registered in the same factory. Walk them
355
+ through it in user terms:
128
356
 
129
- 1. Copy the reference recipe from `templates/workflow-memory.ts` (or
357
+ 1. "I'll add the `workflow-memory` recipe to your project."
358
+ Copy from `templates/workflow-memory.ts` (or
130
359
  `.agentc/smoketest/workflows/workflow-memory.ts` for the smoke
131
- variant) into their project.
132
- 2. `agentc register ./workflow-memory.ts` to install it.
133
- 3. Set `memory: true` on the source workflow(s) — done.
360
+ variant).
361
+ 2. "Run `agentc register ./workflow-memory.ts` once to install it."
362
+ 3. "Now any workflow with `memory: true` will trigger it after each
363
+ successful run."
134
364
 
135
- If they want to skip the built-in and run custom post-run workflows,
136
- use `postRunHooks: [...]` instead. Each post-hook is dispatched in order
137
- with the source run's full context.
365
+ For custom post-run workflows (analytics, audit, notifications)
366
+ without the built-in extractor, use `postRunHooks: [...]` instead.
367
+ Each post-hook runs in declaration order with the source run's full
368
+ context.
@@ -7,6 +7,13 @@ allowed-tools: Bash(agentc *)
7
7
 
8
8
  # Invoke Workflow
9
9
 
10
+ A one-shot dispatch — the CLI POSTs to `/api/v1/factories/<slug>/templates/<name>/invoke`,
11
+ the server creates a run row, the worker boots a sandbox, and the
12
+ workflow runs. Scheduled runs go through the same dispatch path but
13
+ are triggered by a cron tick instead; they're tagged with
14
+ `_scheduleId` + `_scheduleName` on metadata so the dashboard shows
15
+ "schedule by <name>" on the row. This skill is the manual path.
16
+
10
17
  ## Context
11
18
 
12
19
  Registered workflows:
@@ -18,7 +25,8 @@ Registered workflows:
18
25
 
19
26
  The user wants to invoke: **$ARGUMENTS**
20
27
 
21
- If the line above is blank, ask which workflow to invoke. Use the registered workflows list above as suggestions.
28
+ If `$ARGUMENTS` is empty, ask which workflow to invoke. Use the
29
+ registered workflows list above as suggestions.
22
30
 
23
31
  Once you have the workflow name, dispatch it:
24
32
 
@@ -26,17 +34,31 @@ Once you have the workflow name, dispatch it:
26
34
  agentc invoke <name> --follow
27
35
  ```
28
36
 
37
+ Common extra flags:
38
+ - `--input '{"k":"v"}'` — JSON input matching the workflow's `inputSchema`.
39
+ - `--factory <slug>` — invoke into a non-default factory.
40
+ - `--snapshot <snap_…>` — per-invocation `bootFrom` override (per `/ac:snapshots`).
41
+
29
42
  ## Output
30
43
 
31
44
  Stream events as they arrive. When complete, report:
32
- - Final outcome (success / failed)
33
- - Final wall time (`run_complete` includes elapsed seconds)
34
- - Any PR URL, plan URL, or artifact produced (visible in the streamed events
35
- or via `agentc logs <run-id>` after the fact)
45
+ - Final outcome (success / failed / cancelled / abandoned)
46
+ - Wall time (`run_complete` includes elapsed seconds)
47
+ - Any PR URL, plan URL, or artifact emitted (visible in the streamed
48
+ events or via `agentc logs <run-id>` after the fact)
36
49
 
37
50
  ## Next Steps
38
51
 
39
- - **Success** → Report the outcome and any output.
40
- - **Failed** → Show the failure reason. Offer to debug: "Run `/ac:logs <run-id>` for the full event log."
41
- - **Secrets missing** → "Run `/ac:secrets set <workflow> <KEY> <value>` to configure the required secret."
42
- - **Template not found** → "Run `/ac:register <workflow.ts>` to register it first."
52
+ - **Success** → Report outcome + any output emitted.
53
+ - **Failed** → Show the failure reason. Offer `/ac:logs <run-id>` for
54
+ the full event stream.
55
+ - **Secrets missing** → "Run `/ac:secrets set <workflow> <KEY> <value>`
56
+ to configure the required secret."
57
+ - **Template not found** → "Run `/ac:register <workflow.ts>` to
58
+ register it first."
59
+ - **Snapshot missing (`bootFrom` 503)** → The snapshot id this
60
+ workflow boots from was deleted. List captured snapshots
61
+ (`/ac:snapshots`) and update the workflow's `snapshots: { bootFrom }`
62
+ with a current id, then re-register.
63
+ - **Want it to run on a schedule?** → `/ac:schedule create <name>
64
+ --workflow <wf> --cron '<expr>'`.
@@ -7,22 +7,59 @@ allowed-tools: Bash(agentc *)
7
7
 
8
8
  # Register and Invoke
9
9
 
10
- Register the workflow at `$0`, then invoke it.
10
+ Bundle + register a workflow, then dispatch it once and stream the run.
11
+ Tight inner-loop for verifying source-level changes against the server.
12
+
13
+ ## Instructions
14
+
15
+ The user passed: **$ARGUMENTS**
16
+
17
+ If `$ARGUMENTS` is empty, ask for the workflow file path before
18
+ proceeding.
19
+
20
+ Parse out the workflow file (first positional arg, ends in `.ts`).
21
+ Anything after it (`--input`, `--factory`, etc.) is passed through to
22
+ `agentc invoke`.
11
23
 
12
24
  ## Plan
13
25
 
14
26
  ```bash
15
- agentc register $0
16
- agentc invoke $(basename "$0" .ts) --follow $1
27
+ # Register the file:
28
+ agentc register <workflow.ts>
29
+
30
+ # Then invoke it by name (basename minus .ts) and stream:
31
+ agentc invoke <workflow-name> --follow [...invoke flags]
32
+ ```
33
+
34
+ If the user wants the workflow to run on a schedule instead of (or in
35
+ addition to) the one-shot test, suggest `/ac:schedule create` AFTER the
36
+ register completes — schedules live independently of register/invoke
37
+ and shouldn't be mixed into this iteration loop.
38
+
39
+ For the shorthand path (one schedule per workflow, named after the
40
+ workflow), pass `--schedule '<cron>'` to `agentc register`:
41
+
42
+ ```bash
43
+ agentc register <workflow.ts> --schedule '0 9 * * *'
17
44
  ```
18
45
 
19
- If `$ARGUMENTS` is empty, ask for the workflow path first.
46
+ That creates + reconciles the schedule at register time; you still
47
+ need a manual `agentc invoke` to test it without waiting for the next
48
+ tick.
20
49
 
21
50
  ## Output
22
51
 
23
- Show register output, then stream the run. When complete, report outcome and any artifacts.
52
+ Show register output, then stream the run live. When complete, report:
53
+ - Final outcome (success / failed / abandoned)
54
+ - Wall time (from `run_complete`)
55
+ - Any PR URL, plan URL, or artifact emitted along the way
24
56
 
25
57
  ## Next Steps
26
58
 
27
- - **Registration failed** → Fix the error and re-run.
28
- - **Run failed** Show failure reason from the final event. Offer `/ac:logs <run-id>`.
59
+ - **Registration failed** → Re-read the bundler / validator error.
60
+ Usually a missing import path, malformed `defineWorkflow(...)`, or a
61
+ manifest mismatch. Fix and re-run.
62
+ - **Run failed** → Show failure reason from the final event. Offer
63
+ `/ac:logs <run-id>` for the full event stream.
64
+ - **Need a schedule** → `/ac:schedule create <name> --workflow <wf>
65
+ --cron '<expr>'` after this completes.
@@ -36,7 +36,10 @@ Confirm:
36
36
 
37
37
  ## Next Steps
38
38
 
39
- - **Success** → "Registered. Run `/ac:invoke <name>` to test it."
39
+ - **Success** → "Registered. Run `/ac:invoke <name>` to test it.
40
+ Want it on a schedule? `/ac:schedule create <name> --workflow <wf>
41
+ --cron '<expr>'` (or pass `--schedule '<expr>'` next time you
42
+ register for the auto-shorthand)."
40
43
  - **Bundle failed** → Re-read the bundler error; usually a missing import path
41
44
  or a runtime that couldn't be resolved.
42
45
  - **Validation error** → Fix the reported issue in the source file and re-run.