Repository navigation
refresh(writing-relayflows): correct guidance for @relayflows/surface@2.0.16 - #106
Conversation
The skill was verified against a pre-release source build (86a2ec2) and
predates most of the v2 surface's current shape. Refreshed from the
shipped 2.0.16 .d.ts files directly, plus real flows run/check evidence
gathered while building AgentWorkforce/flows-cookbook:
- f.done()'s closed set is 6 values, not 4 (needs_human/declined were
missing; the human-decline example wrongly used done('canceled')).
- Predicate .gate((v) => …) is refused at runtime (unsupported_gate) —
reproduced on two real example flows. Only config-object gates
(subprocess_gate, regex_match, word_count_bounds, references_input)
actually run; the skill previously showed only the broken predicate
form as the TypeScript gate API.
- flows.json's real accepted keys are cli/executors/models/mcp/deploy —
tools/budget/etc. there are config_invalid, not FlowHeader fields.
- New: parallel agents via Promise.all (documented, first-class, with
the process-wide Promise.all replacement disclosure), the
transport: 'relay' dispatch option and what it actually is (task
dispatch + durable receipt, not live agent-to-agent chat), the
--data-dir gotcha when a flow's own git hygiene can delete the
daemon's default data dir mid-run, flows deploy/deployments/undeploy/
schedule, and a currently-open flows run --cloud bug for TS flows
(flows#461).
- Helpers are a generated 40+ provider namespace, not just Slack; two
unrelated things are both spelled "tools" depending on where you
write it, documented explicitly since it's an easy first mistake.
Verified: this file's own TypeScript and YAML examples pass flows check
against @relayflows/surface@2.0.16 / @relayflows/sdk@2.0.16 for real.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Advanced Run ID: Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Devin Review found 3 potential issues.
4 flags not posted on this PR by your GitHub settings — view them in Devin Review. (Configure)
| `f.human` is a durable, journaled approval gate — the run parks until the human answers, and resumes exactly where it left off. `f.dispatch` hands input to a named child flow and returns its typed result; the parent doesn't inline the child's steps. (Source: `docs/SURFACE.md` §2 rule 6 region, lines ~40-53 as of `origin/main@86a2ec2` — this snippet is cited, not independently re-run, since it needs a live daemon.) | ||
|
|
||
| `f.slack` is a separate helper namespace, and its real calling convention doesn't fit a plain `flow(name, async (f) => ...)` body: in the real source, `f.slack.reply(event, ...)` only appears inside a trigger handler registered via `.on(slack.mention('#exec'), async (f, event) => { ... })`, where `event` is the trigger's second callback argument — not something a step-based flow like the one above ever has in scope. Triggers and `f.slack` are out of this skill's scope (see **What this skill does NOT cover**); don't copy a bare `f.slack.reply(event, ...)` call into a `flow()` body like the one above, it will throw `event is not defined`. | ||
| `f.human` is a durable, journaled approval gate — the run parks (`needs_human` is the run-level signal a caller sees while waiting) until the human answers, and resumes exactly where it left off; nothing sits there blocking a thread, and the wait survives a restart exactly like a crash mid-step does. `f.dispatch` hands input to a named child flow and returns its typed result; the parent doesn't inline the child's steps. |
There was a problem hiding this comment.
🟡 Resident verbs fail at runtime
Calling f.human or f.dispatch under 2.0.16 throws unsupported_verb; the shipped executor lowers neither resident verb. The approval flow cannot complete.
Learn more
The shipped surface types expose both methods, but the 2.0.16 SDK executor implements each by throwing unsupported_verb. Type availability therefore does not establish executable support. The sample reaches f.human after its agent step and fails instead of parking for approval. If approval succeeded somehow, f.dispatch would fail identically.
Example: With ok intended to await Khaliq's answer, f.human(...) immediately rejects. No answer can produce declined or continue to garden/implement.
Recommended fix: Mark both verbs as type-only and unsupported by the 2.0.16 executor. Remove the runnable approval example, or replace it only after verifying a package version whose executor lowers both calls.
Was this helpful? React with 👍 or 👎 to provide feedback.
| const plan = await f.agent('planner', { | ||
| task: 'Research and plan: add OAuth2 support', | ||
| workspace: 'acme/api: readonly', // compiles to relayauth path scopes | ||
| workspace: 'acme/api: readonly', |
There was a problem hiding this comment.
🟡 Readonly workspace example is refused
The example's workspace ends in : readonly, which 2.0.16 rejects as unsupported_workspace_permission. The flow stops before requesting approval.
Learn more
The TypeScript surface accepts a workspace string, but the 2.0.16 executor explicitly rejects trailing : readonly and : readwrite annotations. No parser converts those annotations into permissions. Declarative YAML supports a separate permissions field, while this TypeScript call does not.
Example: workspace: 'acme/api: readonly' fails before the planner starts. workspace: 'acme/api' declares the surface without claiming an unenforced restriction.
Recommended fix: Use the bare workspace name in this TypeScript example. Direct readers needing enforced read-only access to the declarative YAML permissions field.
| workspace: 'acme/api: readonly', | |
| workspace: 'acme/api', |
Was this helpful? React with 👍 or 👎 to provide feedback.
| - `exit_code` — implicit default for `deterministic` steps. Not configurable; writing it explicitly is allowed and compiles to the same thing as omitting it. | ||
| - `output_contains` — step output (stdout tail, or the LLM value stringified) contains `value`. | ||
| - `json_schema` — step output validates against a JSON Schema (`boolean | Record<string, unknown>`). Used for structured LLM/agent output; `output?: JsonOutputSchema` on an `llm`/`agent` step is sugar that compiles to this. | ||
| - `subprocess_gate` — runs `command`, judged on its exit code, seeing the step's output via `FLOWS_INPUT`/`from_output`. The gate that actually works for "check a file the agent wrote," e.g. `{ type: 'subprocess_gate', command: 'test -s review.md' }`. |
There was a problem hiding this comment.
🟡 Subprocess gates hide step output
subprocess_gate commands following this guidance read FLOWS_INPUT, but 2.0.16 exposes selected output only as INPUT. Such gates reject valid results.
Learn more
The SDK itself uses FLOWS_INPUT only inside its generated wrapper. That wrapper selects from_output, converts the value to text, and starts the author's command with INPUT in its environment. The later test -s <(cat) example also cannot consume the output because the command receives no stdin and runs under /bin/sh, where process substitution is not portable.
Example: A gate command node -e 'JSON.parse(process.env.FLOWS_INPUT)' receives undefined and fails. Reading process.env.INPUT instead sees the selected step output.
Recommended fix: Document INPUT as the author-command contract and from_output as the optional selection path. Replace the stdin/process-substitution example with a portable command that inspects $INPUT.
Was this helpful? React with 👍 or 👎 to provide feedback.
Devin's review on this PR flagged three issues; verified each directly against the real CLI rather than trusting or dismissing the report: - f.human and f.dispatch both typecheck and pass `flows check`, but the shipped 2.0.16 executor throws `unsupported_verb` for both at `flows run` time. Confirmed. Rewrote the "Human approval and dispatch" section to state this plainly instead of presenting a broken example as working guidance. - workspace: 'acme/api: readonly' is refused (unsupported_workspace_permission) under --local-agent. Confirmed — but the review's suggested fix (drop the `: readonly` suffix) does NOT work either: a bare workspace value fails identically, because the local-agent worker holds no revision pins at all, not because of the permission annotation syntax. Corrected to say omit `workspace` entirely under --local-agent. - subprocess_gate commands see the extracted value as $INPUT, never $FLOWS_INPUT (that's the SDK's own internal wrapper's env var, never exposed to the author's command) — confirmed by reading named-gate-lowering.js directly. Fixed the claim and the broken `test -s <(cat)` placeholder example with a real, run-verified one. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
Verified all three of @devin-ai-integration's findings directly against the real CLI rather than taking them on faith — all confirmed as real bugs, pushed fixes:
Thanks for the catch on all three — good example of why "the type accepts it" and "the executor runs it" are different claims, which is exactly the gap this skill exists to close. |
…ions) Answers a real gap: the skill documented flows deploy's syntax but not what has to already be true for it to succeed. An agent following just the syntax would hit flow_repository_not_connected with no lead on what to fix. Added: agent-relay cloud login is required first (shared with the whole Cloud session, no separate flows login); the workspace needs a GitHub App installation covering --repo and the --on provider must be a connected integration, both checked before flows deploy activates a listener (prepare-flow-deploy.ts in AgentWorkforce/cloud); and this is a different concern from a local git/gh push credential, which matters only for testing a flow's own git steps locally. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Caught right before merging: flows#461 (the flows run --cloud bug for authored TS flows) was closed today by flows#462, a real CLI fix. Re-verified directly against relayflows@2.0.17 rather than trust the issue tracker alone: flows run --cloud --wait <flow.ts> --input now submits successfully and returns a real run id, where 2.0.16 gave an immediate HTTP 400 or misrouted into the declarative loader. Root cause was a Surface version mismatch between Cloud and the CLI, badly reported; the CLI side is fixed, so update rather than work around it. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Summary
The
writing-relayflowsskill was last verified against a pre-release source build (86a2ec2) and predates most of the v2 surface's current shape (published npm was still on2.0.8when it was written). Refreshed directly from the shipped@relayflows/surface@2.0.16/@relayflows/sdk@2.0.16.d.tsfiles, plus realflows check/flows runevidence gathered while building AgentWorkforce/flows-cookbook.What changed
f.done()'s closed set is 6 values, not 4.needs_human/declinedwere missing entirely, and the human-approval example wrongly showedf.done('canceled')for a declined "no" —canceledis kernel-only..gate((v) => …, reason)is refused at runtime (unsupported_gate) — reproduced live on two real example flows inAgentWorkforce/flows(pr-review-pipeline,dependency-upgrade-bot). The old skill showed only this broken form as the TypeScript gate API. Corrected to the config-object form (subprocess_gate,regex_match,word_count_bounds,references_input) that actually runs, with flows#449 noted as the pending fix for predicate gates.flows.json's real accepted keys:cli,executors,models,mcp,deploy— confirmed by both the shipped type and a liveconfig_invalidrefusal. The old skill only documented three of these and didn't warn thattools/budget(realFlowHeaderfields) are invalid there.Promise.all(documented, first-class perdocs/SURFACE.md, with the process-widePromise.allreplacement disclosure), thetransport: 'relay'dispatch option and what it actually is (task dispatch + durable receipt, not live agent-to-agent chat — worded carefully so it isn't overclaimed), the--data-dirgotcha (a flow's owngit cleancan delete the daemon's default data dir mid-run — this cost real debugging time building the cookbook),flows deploy/deployments/undeploy/schedule, and a currently-openflows run --cloudbug for TS flows (flows#461).FlowHeader.tools= helper intent; YAMLFlowSpec.tools= filesystem grants) — an easy first mistake, made once while writing this refresh.Verification
This file's own TypeScript and YAML code examples were re-run through
flows checkagainst the real@relayflows/surface@2.0.16/@relayflows/sdk@2.0.16packages — all pass. The predicate-gate failure, theflows.jsonschema refusal, and the--data-dirinteraction were all reproduced directly, not asserted from memory.Test plan
flows checkthe TypeScript and YAML snippets in this file against@relayflows/surface@2.0.16(already done locally — see above)86a2ec2/2.0.8baseline🤖 Generated with Claude Code
Note
Low Risk
Documentation-only change to a single skill file; no runtime or application code is modified.
Overview
Refreshes the writing-relayflows skill from a pre-release/
2.0.8baseline to @relayflows/surface@2.0.16 / @relayflows/sdk@2.0.16, with run-verified CLI behavior instead of source-only citations.Correctness fixes: documents six
f.done()reasons (needs_human,declined) and kernel-onlycanceled/budget_exceeded; warns that predicate.gate((v) => …)fails at runtime (unsupported_gate) and steers authors to config-object gates; expandsflows.jsonto the realFlowsJsonkeys and invalid top-level fields; statesf.human/f.dispatchandworkspaceunder--local-agenttypecheck but do not execute.New guidance: 40+ Helpers and the two meanings of
tools; parallel agents viaPromise.all;transport: 'relay';flows deploy/schedule,--local-agent,--data-dirvs git-clean gotchas, andflows run --cloudfixed in 2.0.17; updatedCtx(LlmOptions,runtimeout,useheader, budget in examples).Removed/moved: large inline YAML spec blocks and outdated “human approval works” examples; verification baseline now points at flows-cookbook rather than duplicating transcripts.
Reviewed by Cursor Bugbot for commit 1a742e8. Bugbot is set up for automated code reviews on this repo. Configure here.