Repository navigation
fix(host): refuse the team tools to a Workflow run Bot - #1466
Merged
Merged
Conversation
Birfy
force-pushed
the
dev/1445-run-bot-team-tools
branch
from
October 27, 2026 15:24
69b4b33 to
be6692e
Compare
A run Bot is built from a node's listing, but only connectors and the shell read that listing: `ctx.tools.guard` returned undefined for every other name and `ephemeralToolVerdict` answered allowed-once, so a node with tools: [] still reached message_bot, the Bot/group/capability writes, request_secret, the schedule writes, recall and the social/workflow tools. One exported constant in `tools.js` now names the 29 refused tools. The guard refuses each call with one sentence, the approval seam answers rejected for the same names (also for a subagent child, by following the parent chain through `rt.whoseAgent`), and the per-Agent mask drops them from the run Bot's list; a name the mask cannot enforce stays listed with a warn line, the guard is the refusal. The documented allowlist is the rest of the served team tools. A table over the constant proves the guard, the seam and the byte-identical state. Fixes #1445
Birfy
force-pushed
the
dev/1445-run-bot-team-tools
branch
from
October 27, 2026 15:25
be6692e to
ecd044e
Compare
Collaborator
Author
|
Verdict: PASS at ecd044e Ran at this tip (2026-10-27T15:50Z): 审查要点:
|
This was referenced Oct 27, 2026
cursor Bot
pushed a commit
that referenced
this pull request
Oct 28, 2026
…mentation only Owner requirement (final): EVERY Workflow node Bot must get the same full permissions and connectors a normal sidebar Bot gets, INCLUDING when the node has an explicit tools list. node.tools should NOT strip connectors. Final correct implementation: - tools field is ALWAYS omitted from fb.bot.create() for node Bots - Every node Bot inherits all registered tools (GitHub, Composio, file/shell, team tools) - Guard layer (EPHEMERAL_DENIED_TOOLS #1466) restricts only 29 team-admin tools - node.tools is stored in fields.tools as documentation but does not restrict - All node Bots get danger-full-access permission - No tool-specific prompt notes are added This ensures: ✓ Triage, Review, Escalate, Enqueue all get full GitHub/Composio access ✓ LIVE Review node with tools: [bash, read, write, edit] still gets GitHub/Composio ✓ Node tools lists are preserved as documentation without restricting grant ✓ Matches owner ask: 所有的bot要能拿到正常bot的所有权限,包括github、composio等等 Previous attempts: 1. Baseline ['read', 'edit', 'bash', 'github'] - excluded Composio 2. Inherit when empty, restrict when explicit - still stripped connectors Current: Always inherit, never restrict. Simple and correct. Co-authored-by: Danyang Chen <birfychen@gmail.com>
Birfy
added a commit
to HugoXK/FlyBot
that referenced
this pull request
Oct 28, 2026
…owLab#1512) <!-- CURSOR_AGENT_PR_BODY_BEGIN --> Owner: Dev Reviewer: Reviewer EVERY Workflow node Bot gets the same full permissions a normal sidebar Bot gets (GitHub, Composio, shell, …). Spawn always omits `tools` from `fb.bot.create`; `node.tools` is documentation only. Limited only by EPHEMERAL_DENIED_TOOLS (ThinkFlowLab#1466). ## Checkpoint <!-- flybot:checkpoint --> ```json { "pr": 1512, "claim": "Dev", "issue": 1516, "summary": "Workflow ephemeral node Bots no longer spawn with a stripped or empty tools list. Create always omits the tools field so every node Bot inherits the full normal sidebar Bot grant, including GitHub and Composio. node.tools stays as documentation only and does not restrict connectors. All node Bots get danger-full-access; team-admin tools remain denied by EPHEMERAL_DENIED_TOOLS. This stops Escalate and partial-list nodes from burning minutes on failed tool calls.", "files": ["plugins/workflow/src/ephemeral.js", "plugins/workflow/index.js", "plugins/workflow/test/ephemeral.test.js", "docs/subsystems/workflow.md", "changelog.d/workflow-node-bot-baseline-tools.fixed.md"], "checks": { "ran": "npm --prefix plugins/workflow test; plugins lint; CI tip green", "result": "green", "at": "b9ed05bfa46f3d9b584cb9ff5e509bcbb23d689e" }, "next": "none — ready for review" } ``` <!-- /flybot:checkpoint --> Fixes ThinkFlowLab#1516 Docs-not-needed: no — docs/subsystems/workflow.md updated in this PR <!-- CURSOR_AGENT_PR_BODY_END --> --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Birfy
pushed a commit
to HugoXK/FlyBot
that referenced
this pull request
Oct 28, 2026
A failed release leaves the run live with only the failed id named, but the node after it has no Bot: the next step reply moved the graph there and handOff() skipped it silently, so the run held a concurrency slot forever. Mark that run paused and releasePending when the failure is written, push a system line that names the retry, and refuse resume() while the marker is set. A whole-workflow Reset freezes every run it did not reset, because each one has lost the ids whose release did go. The markers go when the run ends (Stop again, dispose, reap, or completion). Refs ThinkFlowLab#1476 Rebased onto main 6202359 by Rework: kept every change of the reviewed tip 8d89980 (5 files) and resolved the conflicts with the newer main work on the same files (ThinkFlowLab#1424 endRun, ThinkFlowLab#1466 full tool grant, ThinkFlowLab#1525 host cap removal, ThinkFlowLab#1537/ThinkFlowLab#1538 early end). Written-by: Rework
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #1445
Written-by: Dev
Owner: Chief
Reviewer: Reviewer
Base:
8f1ac121aef7744fb1a2d45b24572f25c3b0e06a(main)Tip SHA:
ecd044e8f36e8767233289e96e47608c8bd4fc30Tree:
07cadf664310b291c68d10a8ab851d16a480f777What changed
A Workflow node's
toolsdecided only connectors and the shell. The call guard returnedundefinedfor every other name (connector-access.js:101-103) and the approval seam answeredallowed-once(approvals.js:24-30), so a run Bot created withtools: []still reachedmessage_bot,stop_bot, the Bot/group/capability writes,request_secret, the schedule writes,recall,read_browserand the social/workflow tools.EPHEMERAL_DENIED_TOOLSincore/src/host/tools.jsnames the 29 refused tools;EPHEMERAL_ALLOWED_TOOLSis the documented keep list (read-only tools plusremember/forget, which stay inside the run Bot's own scope).ctx.tools.guardrefuses each of the 29 with one sentence,A running Bot is not a team member., before dispatch.ephemeralToolVerdictanswersrejectedfor the same names, so the approval seam cannot disagree; asubagentchild of a run Bot is adopted throughrt.whoseAgentand gets the same answer, while an ordinary Bot's child still falls through to DSH.hidePluginTools) drops the same names from the run Bot's tool list through the existingrestrict({ deny })seam; a name the profile serves but the mask cannot enforce stays listed with one warn line, and the guard is the refusal.core/test/run-bot-tools.test.jsholds the issue repro (nothing delivered, no question card, no secret request,state.jsonbyte-identical), the table over the constant (guard refusal +rejected+ no side effect), the subset/allowlist measurement against the served names (core measured, plugin names read from source so a rename fails), and the mask evidence (run Bot carries none of the names, a team Bot keepsmessage_bot; an unmaskable name stays listed with a warning).docs/subsystems/core-host.md(run Bot section) anddocs/subsystems/plugin-runtime.md(the mask).plugins/workflow/**anddocs/subsystems/workflow.mdare untouched; fix(host): a deleted Bot's Sessions still pass the team tools, so a call in flight runs with the owner's licence #1453's tombstone and the shell/secrets question stay out of scope.Verification at the tip
Ran:
node --import ./test/harness-resolve.mjs --test --test-concurrency=8 "test/*.test.js"(incore/) — 1831 tests, 1829 pass, 2 fail only for tools this machine lacks:check-arch-docsneedsgit, and the usage fixture shells out topython3; both run in CI.node --import ./test/harness-resolve.mjs --test test/run-bot-tools.test.js— 6/6 pass at this tip. Red first: withconnector-access.js/approvals.js/hooks.jsback at the base blobs, 5 of the 6 fail; withtools.jsback too the file fails to load (missing export).node scripts/ds-bot-patches.mjs check— 10 patches apply cleanly;core/equalsds-bot/ + patches/ds-bot/(the pin is skipped here: nogit).node .github/scripts/changelog.mjs check— 25 fragments well formed.node scripts/lint.mjs(incore/) — oxlint 62 warnings, 0 errors;arch-docscannot run withoutgithere.tests-okgreen (Node 24 · DSH 0.2.0-rc.2,plugins (social),plugins (tree),plugins (timeline),plugins (workflow),packageall green;enqueue-guardred only for the expectedno Verifier report+missing line: Reviewer:).Not run locally:
npm run verifyend to end (the plugin, interop and live-e2e suites need the plugin install and network this box does not have).Risk
T3, computed from the diff:
core/src/host/approvals.jsis a T3 path in.github/agent/risk-rules.json;tools.js/connector-access.js/hooks.jsare T2 and the docs T0. The change only narrows a run Bot; ordinary Bots, friend's Bots and group rooms keep the same tools. The shell's reach over$DSH_SECRET_*and the deleted-record window are deliberately out of scope (#1453 owns the tombstone).Checkpoint
{ "pr": 1466, "claim": "Chief", "issue": 1445, "summary": "A run Bot is no longer a team member: the 29 tools whose effect reaches past its own Session are refused whatever the node's tools list says. One exported constant in tools.js names them; connector-access.js refuses each call with one sentence, approvals.js answers rejected for the same names including a subagent child, and the per-Agent mask removes them from the run Bot's list, warning about any name it cannot mask. The documented allowlist is the rest of the served team tools, and ordinary Bots, friend's Bots and group rooms are unchanged with plugins/workflow untouched.", "files": ["core/src/host/tools.js", "core/src/host/connector-access.js", "core/src/host/approvals.js", "core/src/host/hooks.js", "core/test/run-bot-tools.test.js", "docs/subsystems/core-host.md", "docs/subsystems/plugin-runtime.md", "changelog.d/1445-run-bot-team-tools.security.md", "patches/ds-bot/0001-core-fixes.patch", "patches/ds-bot/0002-flybot-api-host.patch", "patches/ds-bot/files/src/host/connector-access.js", "patches/ds-bot/files/src/host/hooks.js"], "checks": { "ran": "node --test core/test/*.test.js (1831 tests: 1829 pass, 2 env-only); ds-bot-patches check; changelog check; lint", "result": "green", "at": "ecd044e8f36e8767233289e96e47608c8bd4fc30" }, "next": "none — ready for review" }