Skip to content

fix(gateway): avoid false Slack API capability denials - #75739

Open
KCAYAAI wants to merge 2 commits into
NousResearch:mainfrom
KCAYAAI:fix/slack-helper-capability-guidance
Open

fix(gateway): avoid false Slack API capability denials#75739
KCAYAAI wants to merge 2 commits into
NousResearch:mainfrom
KCAYAAI:fix/slack-helper-capability-guidance

Conversation

@KCAYAAI

@KCAYAAI KCAYAAI commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Summary

  • replace the absolute Slack API denial with capability-neutral guidance
  • preserve the existing affirmative guidance when dedicated native or MCP Slack tools are detected
  • allow deployments to discover documented, scoped operations supplied by skills, CLIs, plugins, or helpers
  • prohibit broad capability assumptions, raw credentials, undocumented API calls, and unauthorized targets

Root cause

_slack_tools_loaded() detects dedicated native and MCP model-tool surfaces. A false result proves that those dedicated tools are not loaded, but it does not prove that every deployment-provided Slack route is absent.

The previous fallback converted that limited negative signal into an absolute claim:

You do NOT have access to Slack-specific APIs

and:

you still cannot call Slack APIs yourself

That instruction can override a governed deployment skill, CLI, plugin, or helper and cause an agent to refuse an authorized operation that the deployment supports.

Fix

The dedicated-tool branch is unchanged.

When no dedicated native or MCP Slack tool is loaded, the platform note now:

  1. states that limited fact without claiming that all Slack API access is absent;
  2. tells the agent not to assume broad Slack API access;
  3. requires inspection of loaded capabilities before attempting or refusing the work;
  4. recognizes that a documented deployment skill, CLI, plugin, or helper may expose scoped operations;
  5. requires documented operations and authorized targets;
  6. prohibits raw Slack credentials and undocumented API calls.

Why this revision is narrower

An earlier revision added slack.authenticated_api_helper configuration and multiplex propagation. That boolean could describe intent, but it could not verify the installed helper, authenticated identity, supported methods, or authorization scope.

This rewrite removes that configuration surface. It changes only the fallback wording and its regression test.

Test evidence

Current upstream base: f51aa6a9b5ce514e15f8e337777f522fd5cc6fa2

pytest tests/gateway/test_session.py tests/gateway/test_prompt_tail_freeze.py -q
72 passed
pytest tests/gateway -q -k 'slack or prompt_tail'
462 passed, 2 skipped
ruff check gateway/session.py tests/gateway/test_session.py
All checks passed

python -m compileall -q gateway/session.py tests/gateway/test_session.py
git diff --check

The rewritten patch was also independently reviewed against its sealed fingerprint and stable patch ID. The reviewer confirmed that the positive dedicated-tool branch is byte-identical to upstream and found no security concerns or logic errors.

Scope

  • two changed files
  • no new configuration key
  • no Slack credentials or OAuth scope changes
  • no permission grant or authorization bypass
  • no tool registry or MCP behavior change
  • no raw-token surface

Related work

@alt-glitch alt-glitch added type/bug Something isn't working comp/gateway Gateway runner, session dispatch, delivery platform/slack Slack app adapter P3 Low — cosmetic, nice to have sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state labels Aug 1, 2026

@teknium1 teknium1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for isolating the false-negative prompt path. The absolute denial is present on current main at gateway/session.py:584-589, but the proposed fallback currently overcorrects.

Problems

  • gateway/session.py:583-590 promises an authenticated Slack API path whenever _slack_tools_loaded() is false. That detector only checks the native Slack toolset/token and registered Slack-named MCP servers (gateway/session.py:345-388); SessionContext carries no authenticated skill/CLI/helper capability (gateway/session.py:298-317). A Slack deployment with neither route would receive a false availability claim.
  • The new test mocks the detector false without configuring a helper, skill, or CLI API surface, then asserts that access remains available (tests/gateway/test_session.py:175-188). It therefore tests wording rather than the claimed capability condition.

Suggested changes

  • Make the helper guidance conditional on a verified, deployment-exposed capability rather than on the absence of native/MCP tools; retain non-promissory behavior otherwise.
  • Cover both the no-helper fallback and the verified-helper path, including the existing pinned prompt/key contract in gateway/run.py:22240-22249.

Automated hermes-sweeper review.

Comment thread gateway/session.py Outdated
"Do not promise to perform these actions. The gateway may inline the "
"current message's Slack block/attachment payload when available, but "
"you still cannot call Slack APIs yourself."
"**Platform notes:** You are running inside Slack. Slack API "

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_slack_tools_loaded() == false does not establish that this deployment has an authenticated skill, CLI, or helper; it only rules out the native/MCP routes checked at gateway/session.py:345-388. Please make this availability claim conditional on an observable capability, and cover the no-helper configuration so it cannot promise an unavailable API.

@teknium1 teknium1 added sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-caching Sweeper risk: may break/degrade prompt caching or cache-key stability (invariant) sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Aug 1, 2026
@KCAYAAI KCAYAAI changed the title fix(gateway): keep Slack API access when tools are indirect fix(gateway): gate indirect Slack API guidance on deployment capability Aug 1, 2026
@KCAYAAI

KCAYAAI commented Aug 1, 2026

Copy link
Copy Markdown
Contributor Author

Addressed the review feedback in the updated branch. Affirmative helper guidance is now gated by slack.authenticated_api_helper: true; the unset/false path is non-promissory, the declaration participates in the pinned prompt key, and multiplexed profiles resolve it from their own cached config with fail-closed reconnect behavior. Focused verification: 418 passed, 0 failed; Ruff and git diff --check passed.

@KCAYAAI

KCAYAAI commented Aug 1, 2026

Copy link
Copy Markdown
Contributor Author

CI is green except Python slice 5, which failed in the unrelated tests/tools/test_transcription_tools.py::TestRunCommandSttIdleTimeout::test_stderr_progress_extends_beyond_timeout timing test (timeout=0.1s). The PR does not touch transcription code. I reran that exact test locally five times with file retries disabled: 5/5 passed. GitHub did not permit the fork author to rerun the Nous workflow/job, so this needs a maintainer rerun rather than a code change.

@KCAYAAI
KCAYAAI force-pushed the fix/slack-helper-capability-guidance branch from dac753c to 88f551f Compare August 7, 2026 16:19
@KCAYAAI

KCAYAAI commented Aug 7, 2026

Copy link
Copy Markdown
Contributor Author

Rebased onto current main (6e87d43a57) and re-verified — the fix is unchanged and still live-tested against the new base.

Rebase status

  • Branch fix/slack-helper-capability-guidance is now 5 commits on top of main HEAD 6e87d43a57 (was 1,157 commits behind)
  • No conflicts; diff is exactly the PR's original scope: gateway/config.py, gateway/run.py, gateway/session.py, hermes_cli/config_defaults.py, focused gateway tests, and the Slack setup docs

Local verification on the rebased branch

  • Focused gateway suite (the same file set used for the previous 418-test run): 397 passed, 0 failed
  • tests/tools/test_transcription_tools.py::test_stderr_progress_extends_beyond_timeout (the only previously failing check): passes locally, 5/5-style reruns confirm it is timing flake, not a regression
  • ruff check on all changed files: clean; git diff --check origin/main...HEAD: clean

Why this still needs a maintainer action
The only remaining red check on the previous head was that unrelated transcription timing test (timeout=0.1s), which is unchanged on main and not touched by this PR. Fork authors cannot trigger/rerun the Nous workflow, so the check cannot be cleared from this side. The underlying issue is still present on main: gateway/session.py injects the absolute "you still cannot call Slack APIs yourself" denial whenever _slack_tools_loaded() is false, which overrides authorized Slack API helper deployments (repro link in the PR description).

Could a maintainer rerun the failed job (or the full suite) on the new head? Happy to make any further adjustments.

@KCAYAAI
KCAYAAI force-pushed the fix/slack-helper-capability-guidance branch from 88f551f to 292215c Compare August 11, 2026 16:51
@KCAYAAI KCAYAAI changed the title fix(gateway): gate indirect Slack API guidance on deployment capability fix(gateway): avoid false Slack API capability denials Aug 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/gateway Gateway runner, session dispatch, delivery P3 Low — cosmetic, nice to have platform/slack Slack app adapter sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-caching Sweeper risk: may break/degrade prompt caching or cache-key stability (invariant) sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants