You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Re-filed from #442, which can no longer launch a run — see AgentWorkforce/cloud#3768. Scope here is deliberately narrower than #442: the TypeScript authoring-surface parity gap only. Enforcement stays in #442.
Spec citation
docs/RFC-0001-everything-is-a-relayflow.md:237: "An agent step declares its mutable surfaces up front: workspace... Anything undeclared is outside the contract and outside the step's permissions (gate 8 makes this enforceable, not advisory)."
Current state
The declarative kernel spec already has a real, per-step permissions field — AgentStepSpec.permissions?: PermissionsSpec (packages/sdk/src/spec.ts:250):
It compiles to KernelAgentStep.permissions / KernelPermissionsSpec (file_globs / network_allowlist / access_preset, packages/sdk/src/spec.ts:443) and is schema-validated by both the SDK (packages/sdk/src/validate.ts:490, packages/sdk/src/compile.ts:471-472,533-537,637-641) and the kernel (kernel/relayflowd-core/src/spec.rs).
The gap: it is not on the TypeScript authoring surface. AgentOptions in packages/surface/src/context.ts exposes task, workspace, cli, model, cwd, transport — no permissions. So f.agent(name, options) in a .flow.ts file has no way to set it; only the declarative YAML/JSON dialect (or a hand-built StepSpec / compileSpec() call) can.
This is the same class of gap that #310 fixed for cli / model, and that prior fix is the shape to follow.
Scope
Ctx.agent options. Add optional permissions?: PermissionsSpec to AgentOptions in packages/surface/src/context.ts, mirroring AgentStepSpec.permissions exactly (camelCase fileGlobs / networkAllowlist / accessPreset).
Lowering.authored-worker-step.ts's agent() passes options.permissions through onto the compiled step spec when present, exactly the way options.cli / options.model / options.cwd are passed through today.
Docs and tests. Surface + SDK coverage mirroring the existing AgentStepSpec.permissions validation cases.
A message that needs updating with this change
authored-worker-step.ts's agent() currently refuses a per-step AgentOptions.workspace string carrying a ": readonly" / ": readwrite" suffix, telling the author to "use the declarative spec's permissions field, which is real." That is accurate about the field existing and being validated, but it overstates the effect — "real" there means "a real, validated field," not "actually restricts what the agent does." Once permissions is settable from TypeScript, that message should point at the new option and should not imply enforcement that does not exist yet.
Motivating example
constdraft=awaitf.agent("writer",{task: "...",permissions: {fileGlobs: ["drafts/**"],accessPreset: "readwrite"},});constreview=awaitf.agent("reviewer",{task: "Review drafts/post.md and flag issues; do not edit it.",permissions: {fileGlobs: ["drafts/**"],accessPreset: "readonly"},});
Today this cannot be expressed in TypeScript at all.
Explicitly out of scope
Actual enforcement. Nothing reads access_preset / file_globs / network_allowlist today — they appear in exactly one Rust file (kernel/relayflowd-core/src/spec.rs), parsed and validated, never consumed by dispatch, worker, or auth. Wiring them into real relayauth scope-token minting is gate 8 work and stays in flows: AgentOptions has no permissions field in TypeScript, and it isn't enforced yet anywhere #442. Do not attempt it here, and do not describe this change as making permissions enforced.
FlowHeader.workspace / tools.fs.flows: path-scoped auth from workspace:/tools: — SURFACE §2 rule 3 #308 already compiles those into real relayauth-scoped tokens (packages/sdk/src/scope-compiler.ts, packages/sdk/src/mount-registry.ts, wired into preflight.ts:309-313). That mechanism is flow-wide and separate from this per-agent-step field. Leave it alone.
Re-filed from #442, which can no longer launch a run — see AgentWorkforce/cloud#3768. Scope here is deliberately narrower than #442: the TypeScript authoring-surface parity gap only. Enforcement stays in #442.
Spec citation
docs/RFC-0001-everything-is-a-relayflow.md:237: "An agent step declares its mutable surfaces up front: workspace... Anything undeclared is outside the contract and outside the step's permissions (gate 8 makes this enforceable, not advisory)."Current state
The declarative kernel spec already has a real, per-step
permissionsfield —AgentStepSpec.permissions?: PermissionsSpec(packages/sdk/src/spec.ts:250):It compiles to
KernelAgentStep.permissions/KernelPermissionsSpec(file_globs/network_allowlist/access_preset,packages/sdk/src/spec.ts:443) and is schema-validated by both the SDK (packages/sdk/src/validate.ts:490,packages/sdk/src/compile.ts:471-472,533-537,637-641) and the kernel (kernel/relayflowd-core/src/spec.rs).The gap: it is not on the TypeScript authoring surface.
AgentOptionsinpackages/surface/src/context.tsexposestask,workspace,cli,model,cwd,transport— nopermissions. Sof.agent(name, options)in a.flow.tsfile has no way to set it; only the declarative YAML/JSON dialect (or a hand-builtStepSpec/compileSpec()call) can.This is the same class of gap that #310 fixed for
cli/model, and that prior fix is the shape to follow.Scope
Ctx.agentoptions. Add optionalpermissions?: PermissionsSpectoAgentOptionsinpackages/surface/src/context.ts, mirroringAgentStepSpec.permissionsexactly (camelCasefileGlobs/networkAllowlist/accessPreset).authored-worker-step.ts'sagent()passesoptions.permissionsthrough onto the compiled step spec when present, exactly the wayoptions.cli/options.model/options.cwdare passed through today.AgentStepSpec.permissionsvalidation cases.A message that needs updating with this change
authored-worker-step.ts'sagent()currently refuses a per-stepAgentOptions.workspacestring carrying a": readonly"/": readwrite"suffix, telling the author to "use the declarative spec'spermissionsfield, which is real." That is accurate about the field existing and being validated, but it overstates the effect — "real" there means "a real, validated field," not "actually restricts what the agent does." Oncepermissionsis settable from TypeScript, that message should point at the new option and should not imply enforcement that does not exist yet.Motivating example
Today this cannot be expressed in TypeScript at all.
Explicitly out of scope
access_preset/file_globs/network_allowlisttoday — they appear in exactly one Rust file (kernel/relayflowd-core/src/spec.rs), parsed and validated, never consumed by dispatch, worker, or auth. Wiring them into real relayauth scope-token minting is gate 8 work and stays in flows: AgentOptions has no permissions field in TypeScript, and it isn't enforced yet anywhere #442. Do not attempt it here, and do not describe this change as making permissions enforced.FlowHeader.workspace/tools.fs. flows: path-scoped auth from workspace:/tools: — SURFACE §2 rule 3 #308 already compiles those into real relayauth-scoped tokens (packages/sdk/src/scope-compiler.ts,packages/sdk/src/mount-registry.ts, wired intopreflight.ts:309-313). That mechanism is flow-wide and separate from this per-agent-step field. Leave it alone.🤖 Generated with Claude Code