Skip to content

Slack human-assistance: 'missing required scope: fs:write' should re-mint a write-scoped token instead of hard-failing #17

Description

@khaliqgant

Summary

When a workflow uses swarm.humanAssistance.slack with integrations.relayfile and the active delegated Relayfile credential is read-only (or its write scope has expired), the Slack question write fails with:

[ask-human] Slack human question failed: missing required scope: fs:write

and the runner does not re-mint a write-scoped token. The step hard-fails even though the identity is entitled to fs:write (re-minting joinWorkspace with relayfile:fs:write:/slack/channels/** succeeds when done manually).

Root cause

In @relayflows/core runner.js, askSlackViaRelayfileaskSlackViaRelayfileRuntime only retries after refreshing the token when the error is classified as expired auth:

isRelayfileAuthExpiredError(err) {
  const message = err instanceof Error ? err.message : String(err);
  return /token has expired|jwt expired|unauthorized|401/i.test(message);
}

A missing required scope: fs:write rejection does not match this pattern, so the for (let attempt = 0; attempt < 2; attempt++) loop rethrows on the first attempt and never calls issueFreshRelayfileRuntimeToken (which would request the slack write fallback scopes and succeed).

Impact

  • Any relayflow that posts a Slack human-assistance question fails the moment the local delegated Slack write token lapses (these are short-lived — observed ~24h TTL), with a confusing "missing required scope" error.
  • agent-relay cloud login does not fix it (that refreshes the CLI token, not the delegated Relayfile write scope), so the failure looks unrecoverable to the user.

Suggested fix

Treat missing required scope (specifically an fs:write scope rejection) as a re-mintable condition: extend isRelayfileAuthExpiredError (or add a sibling isRelayfileScopeError) so the runtime calls issueFreshRelayfileRuntimeToken and retries with the slack write fallback scopes before failing.

Environment

  • @relayflows/core 1.0.4 (@relayflows/cli 1.0.4), local relayflows run
  • Workflow: swarm.humanAssistance.slack + integrations.relayfile: {}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions