🪢 feat: Enable Tool-Output References for Bash Tool#12830
Conversation
…k and package.json files This commit updates the version of the `@librechat/agents` package from `3.1.70` to `3.1.71-dev.0` in the `package-lock.json` and relevant `package.json` files. Additionally, it marks several dependencies as peer dependencies, ensuring better compatibility and integration across the project.
Wires `@librechat/agents`' `RunConfig.toolOutputReferences` into
`createRun()` and the bash tool's LLM-facing description, gated by the
per-agent `effectiveCodeEnvAvailable` flag. The feature auto-activates
for any run where the bash tool is actually registered; SDK defaults
(~400 KB per output, 5 MB total) match the shell-safe budget. No new
env var or yaml capability — piggybacks on the existing `execute_code`
gate.
- `tools.ts`: replace the module-level `BASH_TOOL_DEF` constant with a
per-call `buildBashToolDef` that wraps `buildBashExecutionToolDescription`.
Description now includes the `{{tool<idx>turn<turn>}}` reference syntax
guide iff the new `enableToolOutputReferences` param is true.
- `initialize.ts`: pass `enableToolOutputReferences: effectiveCodeEnvAvailable`
into `registerCodeExecutionTools`.
- `run.ts`: add `codeEnvAvailable?: boolean` to `RunAgent`, compute the
flag from `agents[*].codeEnvAvailable`, and conditionally spread
`toolOutputReferences: { enabled: true }` into `Run.create`.
- `tools.spec.ts`: 3 new cases asserting `bash_tool.description`
contains `{{tool<idx>turn<turn>}}` iff `enableToolOutputReferences` is
true (and unset → false).
- `run-summarization.test.ts`: 4 new cases asserting `Run.create` is
invoked with `toolOutputReferences: { enabled: true }` iff at least
one `RunAgent.codeEnvAvailable === true`. Covers the present /
absent / unset / multi-agent-OR cases.
- `initialize.test.ts` + `skills.test.ts`: extend the existing
`@librechat/agents` jest mocks with a `buildBashExecutionToolDescription`
stub so suites stay green when the on-disk SDK lags the published
3.1.71-dev.0 export.
There was a problem hiding this comment.
Pull request overview
Adds support for tool-output reference syntax in the agent bash tool flow by (a) updating the bash_tool description to include the {{tool<idx>turn<turn>}} guide when enabled, and (b) gating the SDK’s toolOutputReferences run setting so it’s only turned on when code execution is actually available for at least one agent.
Changes:
- Extend
registerCodeExecutionToolsto optionally generate abash_tooldescription that documents tool-output reference substitution. - Enable
RunConfig.toolOutputReferencesincreateRunwhen any agent is initialized withcodeEnvAvailable=true. - Update tests/mocks to cover the new description behavior and run-level gating; bump
@librechat/agentsto a version that exports the new description builder.
Reviewed changes
Copilot reviewed 9 out of 10 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/api/src/agents/tools.ts | Adds enableToolOutputReferences flag and builds bash_tool description via SDK helper. |
| packages/api/src/agents/tools.spec.ts | Adds unit tests validating bash_tool description behavior under the new flag. |
| packages/api/src/agents/run.ts | Gates toolOutputReferences on agents.some(codeEnvAvailable). |
| packages/api/src/agents/initialize.ts | Forwards the per-agent effectiveCodeEnvAvailable gate into tool registration. |
| packages/api/src/agents/tests/skills.test.ts | Extends SDK mock to include buildBashExecutionToolDescription. |
| packages/api/src/agents/tests/run-summarization.test.ts | Adds tests asserting presence/absence of toolOutputReferences in Run.create config. |
| packages/api/src/agents/tests/initialize.test.ts | Adds partial mock for buildBashExecutionToolDescription for SDK-version tolerance. |
| packages/api/package.json | Bumps @librechat/agents peer dependency to ^3.1.71-dev.0. |
| api/package.json | Bumps @librechat/agents dependency to ^3.1.71-dev.0. |
| package-lock.json | Updates lockfile for the @librechat/agents bump and related dependency metadata. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| * Builds the `bash_tool` definition. The description varies with | ||
| * `enableToolOutputReferences`: when `true`, the SDK appends an | ||
| * LLM-facing guide explaining the `{{tool<idx>turn<turn>}}` substitution | ||
| * syntax, so the model knows to reuse prior outputs without echoing | ||
| * them. Per-call (not module-level) because the description differs | ||
| * per agent based on the per-run codeenv gate. | ||
| */ | ||
| function buildBashToolDef(opts: { enableToolOutputReferences: boolean }): LCTool { | ||
| return Object.freeze({ | ||
| name: BashExecutionToolDefinition.name, | ||
| description: buildBashExecutionToolDescription({ | ||
| enableToolOutputReferences: opts.enableToolOutputReferences, | ||
| }), | ||
| parameters: BashExecutionToolDefinition.schema as unknown as LCTool['parameters'], | ||
| }) as LCTool; | ||
| } | ||
|
|
There was a problem hiding this comment.
buildBashToolDef() allocates and freezes a new bash_tool definition on every registerCodeExecutionTools() call (including the common second-call no-op path). Since the description only varies by a boolean, consider caching two frozen defs (enabled/disabled) at module scope and selecting between them to preserve the original “no re-allocation” intent.
| * Builds the `bash_tool` definition. The description varies with | |
| * `enableToolOutputReferences`: when `true`, the SDK appends an | |
| * LLM-facing guide explaining the `{{tool<idx>turn<turn>}}` substitution | |
| * syntax, so the model knows to reuse prior outputs without echoing | |
| * them. Per-call (not module-level) because the description differs | |
| * per agent based on the per-run codeenv gate. | |
| */ | |
| function buildBashToolDef(opts: { enableToolOutputReferences: boolean }): LCTool { | |
| return Object.freeze({ | |
| name: BashExecutionToolDefinition.name, | |
| description: buildBashExecutionToolDescription({ | |
| enableToolOutputReferences: opts.enableToolOutputReferences, | |
| }), | |
| parameters: BashExecutionToolDefinition.schema as unknown as LCTool['parameters'], | |
| }) as LCTool; | |
| } | |
| * Builds a frozen `bash_tool` definition for the provided | |
| * `enableToolOutputReferences` mode. | |
| * | |
| * Only the description varies, so the two possible definitions are | |
| * cached once at module scope and reused by | |
| * `registerCodeExecutionTools()` to avoid re-allocation on repeated | |
| * calls, including common idempotent no-op paths. | |
| */ | |
| function createBashToolDef(enableToolOutputReferences: boolean): LCTool { | |
| return Object.freeze({ | |
| name: BashExecutionToolDefinition.name, | |
| description: buildBashExecutionToolDescription({ | |
| enableToolOutputReferences, | |
| }), | |
| parameters: BashExecutionToolDefinition.schema as unknown as LCTool['parameters'], | |
| }) as LCTool; | |
| } | |
| const BASH_TOOL_DEF_WITH_OUTPUT_REFERENCES = createBashToolDef(true); | |
| const BASH_TOOL_DEF_WITHOUT_OUTPUT_REFERENCES = createBashToolDef(false); | |
| function buildBashToolDef(opts: { enableToolOutputReferences: boolean }): LCTool { | |
| return opts.enableToolOutputReferences | |
| ? BASH_TOOL_DEF_WITH_OUTPUT_REFERENCES | |
| : BASH_TOOL_DEF_WITHOUT_OUTPUT_REFERENCES; | |
| } |
GitNexus: 🚀 deployedThe |
…e-lock and package.json files This commit updates the version of the `@librechat/agents` package from `3.1.71-dev.0` to `3.1.71-dev.1` across the relevant package files. This change ensures consistency and incorporates any updates or fixes from the new version.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4261cc4a95
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| * payloads inside typical shell ARG_MAX limits, so no overrides are | ||
| * needed for the experimental rollout. | ||
| */ | ||
| const enableToolOutputReferences = agents.some((a) => a.codeEnvAvailable === true); |
There was a problem hiding this comment.
Include subagents in toolOutputReferences gate
toolOutputReferences is currently gated only by the top-level agents list, but this same function builds nested execution targets from subagentAgentConfigs right above. When a parent agent has codeEnvAvailable !== true and only a child/subagent has codeEnvAvailable === true, this check evaluates false and Run.create omits toolOutputReferences, so {{tool<idx>turn<turn>}} placeholders in that subagent’s bash_tool calls are not resolved even though the child can be configured for code execution.
Useful? React with 👍 / 👎.
GitNexus: 🚀 deployedThe |
Codex P2 review on PR #12830: the run-level `enableToolOutputReferences` flag only inspected the top-level `agents` array. A parent agent without `execute_code` that spawns a subagent that *does* have it left the SDK's tool-output reference registry inactive for the run, so the subagent's `bash_tool` calls saw `{{tool<idx>turn<turn>}}` placeholders pass through to the shell unsubstituted. Replace `agents.some(a => a.codeEnvAvailable === true)` with a recursive `anyAgentHasCodeEnv` helper that walks `subagentAgentConfigs` transitively. Cycle-safe via a `visited` set, mirroring the existing `buildSubagentConfigs.ancestors` pattern in the same module. The bash tool *description* stays per-agent in `initializeAgent` (only agents with bash actually registered learn the `{{…}}` syntax), so broadening the run-level gate doesn't broaden the model-facing surface — it just lets the SDK's shared registry serve every `ToolNode` the run compiles, which is exactly the contract the SDK already implements. Tests cover three new cases: parent-off / subagent-on, parent-off / child-off / grandchild-on (transitive descent past one level), and a cyclic A↔B tree with neither codeenv-enabled (asserts both termination and absence of `toolOutputReferences`). Existing single-agent and multi-agent tests stay valid since the new helper returns `true` whenever the previous `.some(...)` did.
|
@codex review |
|
Codex Review: Didn't find any major issues. Breezy! ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
GitNexus: 🚀 deployedThe |
… and package.json files This commit updates the version of the `@librechat/agents` package from `3.1.71-dev.1` to `3.1.71` across the relevant package files. This change ensures consistency and incorporates any updates or fixes from the stable release.
GitNexus: 🚀 deployedThe |
Two findings from comprehensive PR review on #12830: #1 (MINOR) — `injectSkillCatalog` omitted `enableToolOutputReferences` when calling `registerCodeExecutionTools`, so its resulting `bash_tool` description always lacked the `{{tool<idx>turn<turn>}}` guide. Today this is a no-op because `initializeAgent` registers first and the registry `.has()` check makes the skills-path call a dedupe-only operation. But if call order ever flips (skills-first), the missing flag would silently ship a `bash_tool` without the syntax guide, and the `initializeAgent` pass would itself become the no-op — the feature would silently break with no visible error. Forward `enableToolOutputReferences: codeEnvAvailable === true` so both call sites produce identical tool definitions regardless of firing order. Defense-in-depth, not a current bug. Added a test in `skills.test.ts` that asserts the bash description contains the `{{tool<idx>turn<turn>}}` marker when `codeEnvAvailable` is on, exercising the skills caller end-to-end. #2 (NIT) — `buildBashToolDef` allocated + froze a fresh object on every agent init. Replaced with two module-level frozen singletons (`BASH_TOOL_DEF_WITH_OUTPUT_REFS`, `BASH_TOOL_DEF_WITHOUT_OUTPUT_REFS`) built once at module load via a `createBashToolDef` helper. The factory now picks the right cached reference instead of building. Restores the no-allocation intent of the original `BASH_TOOL_DEF` constant while keeping the per-agent gate behavior. Two new tests in `tools.spec.ts` pin the contract: identical-flag calls return reference-equal `bash_tool` defs across registries; opposite-flag calls return distinct frozen objects with the expected description content.
GitNexus: 🚀 deployedThe |
* chore: Update `@librechat/agents` to v3.1.71-dev.0 across package-lock and package.json files
This commit updates the version of the `@librechat/agents` package from `3.1.70` to `3.1.71-dev.0` in the `package-lock.json` and relevant `package.json` files. Additionally, it marks several dependencies as peer dependencies, ensuring better compatibility and integration across the project.
* 🔗 feat: Enable Tool-Output References for bash_tool when codeenv is on
Wires `@librechat/agents`' `RunConfig.toolOutputReferences` into
`createRun()` and the bash tool's LLM-facing description, gated by the
per-agent `effectiveCodeEnvAvailable` flag. The feature auto-activates
for any run where the bash tool is actually registered; SDK defaults
(~400 KB per output, 5 MB total) match the shell-safe budget. No new
env var or yaml capability — piggybacks on the existing `execute_code`
gate.
- `tools.ts`: replace the module-level `BASH_TOOL_DEF` constant with a
per-call `buildBashToolDef` that wraps `buildBashExecutionToolDescription`.
Description now includes the `{{tool<idx>turn<turn>}}` reference syntax
guide iff the new `enableToolOutputReferences` param is true.
- `initialize.ts`: pass `enableToolOutputReferences: effectiveCodeEnvAvailable`
into `registerCodeExecutionTools`.
- `run.ts`: add `codeEnvAvailable?: boolean` to `RunAgent`, compute the
flag from `agents[*].codeEnvAvailable`, and conditionally spread
`toolOutputReferences: { enabled: true }` into `Run.create`.
* 🧪 test: Cover tool-output references gating end-to-end
- `tools.spec.ts`: 3 new cases asserting `bash_tool.description`
contains `{{tool<idx>turn<turn>}}` iff `enableToolOutputReferences` is
true (and unset → false).
- `run-summarization.test.ts`: 4 new cases asserting `Run.create` is
invoked with `toolOutputReferences: { enabled: true }` iff at least
one `RunAgent.codeEnvAvailable === true`. Covers the present /
absent / unset / multi-agent-OR cases.
- `initialize.test.ts` + `skills.test.ts`: extend the existing
`@librechat/agents` jest mocks with a `buildBashExecutionToolDescription`
stub so suites stay green when the on-disk SDK lags the published
3.1.71-dev.0 export.
* chore: Update `@librechat/agents` version to `3.1.71-dev.1` in package-lock and package.json files
This commit updates the version of the `@librechat/agents` package from `3.1.71-dev.0` to `3.1.71-dev.1` across the relevant package files. This change ensures consistency and incorporates any updates or fixes from the new version.
* 🪢 fix: Walk Subagents in toolOutputReferences run-level gate
Codex P2 review on PR danny-avila#12830: the run-level
`enableToolOutputReferences` flag only inspected the top-level
`agents` array. A parent agent without `execute_code` that spawns a
subagent that *does* have it left the SDK's tool-output reference
registry inactive for the run, so the subagent's `bash_tool` calls
saw `{{tool<idx>turn<turn>}}` placeholders pass through to the
shell unsubstituted.
Replace `agents.some(a => a.codeEnvAvailable === true)` with a
recursive `anyAgentHasCodeEnv` helper that walks
`subagentAgentConfigs` transitively. Cycle-safe via a `visited` set,
mirroring the existing `buildSubagentConfigs.ancestors` pattern in
the same module. The bash tool *description* stays per-agent in
`initializeAgent` (only agents with bash actually registered learn
the `{{…}}` syntax), so broadening the run-level gate doesn't
broaden the model-facing surface — it just lets the SDK's shared
registry serve every `ToolNode` the run compiles, which is exactly
the contract the SDK already implements.
Tests cover three new cases: parent-off / subagent-on, parent-off /
child-off / grandchild-on (transitive descent past one level), and
a cyclic A↔B tree with neither codeenv-enabled (asserts both
termination and absence of `toolOutputReferences`). Existing
single-agent and multi-agent tests stay valid since the new helper
returns `true` whenever the previous `.some(...)` did.
* chore: Update `@librechat/agents` version to `3.1.71` in package-lock and package.json files
This commit updates the version of the `@librechat/agents` package from `3.1.71-dev.1` to `3.1.71` across the relevant package files. This change ensures consistency and incorporates any updates or fixes from the stable release.
* review: address audit findings on tool-output references PR
Two findings from comprehensive PR review on danny-avila#12830:
danny-avila#1 (MINOR) — `injectSkillCatalog` omitted `enableToolOutputReferences`
when calling `registerCodeExecutionTools`, so its resulting
`bash_tool` description always lacked the `{{tool<idx>turn<turn>}}`
guide. Today this is a no-op because `initializeAgent` registers
first and the registry `.has()` check makes the skills-path call a
dedupe-only operation. But if call order ever flips (skills-first),
the missing flag would silently ship a `bash_tool` without the
syntax guide, and the `initializeAgent` pass would itself become
the no-op — the feature would silently break with no visible error.
Forward `enableToolOutputReferences: codeEnvAvailable === true` so
both call sites produce identical tool definitions regardless of
firing order. Defense-in-depth, not a current bug. Added a test in
`skills.test.ts` that asserts the bash description contains the
`{{tool<idx>turn<turn>}}` marker when `codeEnvAvailable` is on,
exercising the skills caller end-to-end.
danny-avila#2 (NIT) — `buildBashToolDef` allocated + froze a fresh object on
every agent init. Replaced with two module-level frozen singletons
(`BASH_TOOL_DEF_WITH_OUTPUT_REFS`, `BASH_TOOL_DEF_WITHOUT_OUTPUT_REFS`)
built once at module load via a `createBashToolDef` helper. The
factory now picks the right cached reference instead of building.
Restores the no-allocation intent of the original `BASH_TOOL_DEF`
constant while keeping the per-agent gate behavior. Two new tests
in `tools.spec.ts` pin the contract: identical-flag calls return
reference-equal `bash_tool` defs across registries; opposite-flag
calls return distinct frozen objects with the expected description
content.
* chore: Update `@librechat/agents` to v3.1.71-dev.0 across package-lock and package.json files
This commit updates the version of the `@librechat/agents` package from `3.1.70` to `3.1.71-dev.0` in the `package-lock.json` and relevant `package.json` files. Additionally, it marks several dependencies as peer dependencies, ensuring better compatibility and integration across the project.
* 🔗 feat: Enable Tool-Output References for bash_tool when codeenv is on
Wires `@librechat/agents`' `RunConfig.toolOutputReferences` into
`createRun()` and the bash tool's LLM-facing description, gated by the
per-agent `effectiveCodeEnvAvailable` flag. The feature auto-activates
for any run where the bash tool is actually registered; SDK defaults
(~400 KB per output, 5 MB total) match the shell-safe budget. No new
env var or yaml capability — piggybacks on the existing `execute_code`
gate.
- `tools.ts`: replace the module-level `BASH_TOOL_DEF` constant with a
per-call `buildBashToolDef` that wraps `buildBashExecutionToolDescription`.
Description now includes the `{{tool<idx>turn<turn>}}` reference syntax
guide iff the new `enableToolOutputReferences` param is true.
- `initialize.ts`: pass `enableToolOutputReferences: effectiveCodeEnvAvailable`
into `registerCodeExecutionTools`.
- `run.ts`: add `codeEnvAvailable?: boolean` to `RunAgent`, compute the
flag from `agents[*].codeEnvAvailable`, and conditionally spread
`toolOutputReferences: { enabled: true }` into `Run.create`.
* 🧪 test: Cover tool-output references gating end-to-end
- `tools.spec.ts`: 3 new cases asserting `bash_tool.description`
contains `{{tool<idx>turn<turn>}}` iff `enableToolOutputReferences` is
true (and unset → false).
- `run-summarization.test.ts`: 4 new cases asserting `Run.create` is
invoked with `toolOutputReferences: { enabled: true }` iff at least
one `RunAgent.codeEnvAvailable === true`. Covers the present /
absent / unset / multi-agent-OR cases.
- `initialize.test.ts` + `skills.test.ts`: extend the existing
`@librechat/agents` jest mocks with a `buildBashExecutionToolDescription`
stub so suites stay green when the on-disk SDK lags the published
3.1.71-dev.0 export.
* chore: Update `@librechat/agents` version to `3.1.71-dev.1` in package-lock and package.json files
This commit updates the version of the `@librechat/agents` package from `3.1.71-dev.0` to `3.1.71-dev.1` across the relevant package files. This change ensures consistency and incorporates any updates or fixes from the new version.
* 🪢 fix: Walk Subagents in toolOutputReferences run-level gate
Codex P2 review on PR danny-avila#12830: the run-level
`enableToolOutputReferences` flag only inspected the top-level
`agents` array. A parent agent without `execute_code` that spawns a
subagent that *does* have it left the SDK's tool-output reference
registry inactive for the run, so the subagent's `bash_tool` calls
saw `{{tool<idx>turn<turn>}}` placeholders pass through to the
shell unsubstituted.
Replace `agents.some(a => a.codeEnvAvailable === true)` with a
recursive `anyAgentHasCodeEnv` helper that walks
`subagentAgentConfigs` transitively. Cycle-safe via a `visited` set,
mirroring the existing `buildSubagentConfigs.ancestors` pattern in
the same module. The bash tool *description* stays per-agent in
`initializeAgent` (only agents with bash actually registered learn
the `{{…}}` syntax), so broadening the run-level gate doesn't
broaden the model-facing surface — it just lets the SDK's shared
registry serve every `ToolNode` the run compiles, which is exactly
the contract the SDK already implements.
Tests cover three new cases: parent-off / subagent-on, parent-off /
child-off / grandchild-on (transitive descent past one level), and
a cyclic A↔B tree with neither codeenv-enabled (asserts both
termination and absence of `toolOutputReferences`). Existing
single-agent and multi-agent tests stay valid since the new helper
returns `true` whenever the previous `.some(...)` did.
* chore: Update `@librechat/agents` version to `3.1.71` in package-lock and package.json files
This commit updates the version of the `@librechat/agents` package from `3.1.71-dev.1` to `3.1.71` across the relevant package files. This change ensures consistency and incorporates any updates or fixes from the stable release.
* review: address audit findings on tool-output references PR
Two findings from comprehensive PR review on danny-avila#12830:
danny-avila#1 (MINOR) — `injectSkillCatalog` omitted `enableToolOutputReferences`
when calling `registerCodeExecutionTools`, so its resulting
`bash_tool` description always lacked the `{{tool<idx>turn<turn>}}`
guide. Today this is a no-op because `initializeAgent` registers
first and the registry `.has()` check makes the skills-path call a
dedupe-only operation. But if call order ever flips (skills-first),
the missing flag would silently ship a `bash_tool` without the
syntax guide, and the `initializeAgent` pass would itself become
the no-op — the feature would silently break with no visible error.
Forward `enableToolOutputReferences: codeEnvAvailable === true` so
both call sites produce identical tool definitions regardless of
firing order. Defense-in-depth, not a current bug. Added a test in
`skills.test.ts` that asserts the bash description contains the
`{{tool<idx>turn<turn>}}` marker when `codeEnvAvailable` is on,
exercising the skills caller end-to-end.
danny-avila#2 (NIT) — `buildBashToolDef` allocated + froze a fresh object on
every agent init. Replaced with two module-level frozen singletons
(`BASH_TOOL_DEF_WITH_OUTPUT_REFS`, `BASH_TOOL_DEF_WITHOUT_OUTPUT_REFS`)
built once at module load via a `createBashToolDef` helper. The
factory now picks the right cached reference instead of building.
Restores the no-allocation intent of the original `BASH_TOOL_DEF`
constant while keeping the per-agent gate behavior. Two new tests
in `tools.spec.ts` pin the contract: identical-flag calls return
reference-equal `bash_tool` defs across registries; opposite-flag
calls return distinct frozen objects with the expected description
content.
* chore: Update `@librechat/agents` to v3.1.71-dev.0 across package-lock and package.json files
This commit updates the version of the `@librechat/agents` package from `3.1.70` to `3.1.71-dev.0` in the `package-lock.json` and relevant `package.json` files. Additionally, it marks several dependencies as peer dependencies, ensuring better compatibility and integration across the project.
* 🔗 feat: Enable Tool-Output References for bash_tool when codeenv is on
Wires `@librechat/agents`' `RunConfig.toolOutputReferences` into
`createRun()` and the bash tool's LLM-facing description, gated by the
per-agent `effectiveCodeEnvAvailable` flag. The feature auto-activates
for any run where the bash tool is actually registered; SDK defaults
(~400 KB per output, 5 MB total) match the shell-safe budget. No new
env var or yaml capability — piggybacks on the existing `execute_code`
gate.
- `tools.ts`: replace the module-level `BASH_TOOL_DEF` constant with a
per-call `buildBashToolDef` that wraps `buildBashExecutionToolDescription`.
Description now includes the `{{tool<idx>turn<turn>}}` reference syntax
guide iff the new `enableToolOutputReferences` param is true.
- `initialize.ts`: pass `enableToolOutputReferences: effectiveCodeEnvAvailable`
into `registerCodeExecutionTools`.
- `run.ts`: add `codeEnvAvailable?: boolean` to `RunAgent`, compute the
flag from `agents[*].codeEnvAvailable`, and conditionally spread
`toolOutputReferences: { enabled: true }` into `Run.create`.
* 🧪 test: Cover tool-output references gating end-to-end
- `tools.spec.ts`: 3 new cases asserting `bash_tool.description`
contains `{{tool<idx>turn<turn>}}` iff `enableToolOutputReferences` is
true (and unset → false).
- `run-summarization.test.ts`: 4 new cases asserting `Run.create` is
invoked with `toolOutputReferences: { enabled: true }` iff at least
one `RunAgent.codeEnvAvailable === true`. Covers the present /
absent / unset / multi-agent-OR cases.
- `initialize.test.ts` + `skills.test.ts`: extend the existing
`@librechat/agents` jest mocks with a `buildBashExecutionToolDescription`
stub so suites stay green when the on-disk SDK lags the published
3.1.71-dev.0 export.
* chore: Update `@librechat/agents` version to `3.1.71-dev.1` in package-lock and package.json files
This commit updates the version of the `@librechat/agents` package from `3.1.71-dev.0` to `3.1.71-dev.1` across the relevant package files. This change ensures consistency and incorporates any updates or fixes from the new version.
* 🪢 fix: Walk Subagents in toolOutputReferences run-level gate
Codex P2 review on PR danny-avila#12830: the run-level
`enableToolOutputReferences` flag only inspected the top-level
`agents` array. A parent agent without `execute_code` that spawns a
subagent that *does* have it left the SDK's tool-output reference
registry inactive for the run, so the subagent's `bash_tool` calls
saw `{{tool<idx>turn<turn>}}` placeholders pass through to the
shell unsubstituted.
Replace `agents.some(a => a.codeEnvAvailable === true)` with a
recursive `anyAgentHasCodeEnv` helper that walks
`subagentAgentConfigs` transitively. Cycle-safe via a `visited` set,
mirroring the existing `buildSubagentConfigs.ancestors` pattern in
the same module. The bash tool *description* stays per-agent in
`initializeAgent` (only agents with bash actually registered learn
the `{{…}}` syntax), so broadening the run-level gate doesn't
broaden the model-facing surface — it just lets the SDK's shared
registry serve every `ToolNode` the run compiles, which is exactly
the contract the SDK already implements.
Tests cover three new cases: parent-off / subagent-on, parent-off /
child-off / grandchild-on (transitive descent past one level), and
a cyclic A↔B tree with neither codeenv-enabled (asserts both
termination and absence of `toolOutputReferences`). Existing
single-agent and multi-agent tests stay valid since the new helper
returns `true` whenever the previous `.some(...)` did.
* chore: Update `@librechat/agents` version to `3.1.71` in package-lock and package.json files
This commit updates the version of the `@librechat/agents` package from `3.1.71-dev.1` to `3.1.71` across the relevant package files. This change ensures consistency and incorporates any updates or fixes from the stable release.
* review: address audit findings on tool-output references PR
Two findings from comprehensive PR review on danny-avila#12830:
#1 (MINOR) — `injectSkillCatalog` omitted `enableToolOutputReferences`
when calling `registerCodeExecutionTools`, so its resulting
`bash_tool` description always lacked the `{{tool<idx>turn<turn>}}`
guide. Today this is a no-op because `initializeAgent` registers
first and the registry `.has()` check makes the skills-path call a
dedupe-only operation. But if call order ever flips (skills-first),
the missing flag would silently ship a `bash_tool` without the
syntax guide, and the `initializeAgent` pass would itself become
the no-op — the feature would silently break with no visible error.
Forward `enableToolOutputReferences: codeEnvAvailable === true` so
both call sites produce identical tool definitions regardless of
firing order. Defense-in-depth, not a current bug. Added a test in
`skills.test.ts` that asserts the bash description contains the
`{{tool<idx>turn<turn>}}` marker when `codeEnvAvailable` is on,
exercising the skills caller end-to-end.
#2 (NIT) — `buildBashToolDef` allocated + froze a fresh object on
every agent init. Replaced with two module-level frozen singletons
(`BASH_TOOL_DEF_WITH_OUTPUT_REFS`, `BASH_TOOL_DEF_WITHOUT_OUTPUT_REFS`)
built once at module load via a `createBashToolDef` helper. The
factory now picks the right cached reference instead of building.
Restores the no-allocation intent of the original `BASH_TOOL_DEF`
constant while keeping the per-agent gate behavior. Two new tests
in `tools.spec.ts` pin the contract: identical-flag calls return
reference-equal `bash_tool` defs across registries; opposite-flag
calls return distinct frozen objects with the expected description
content.
Context:
Summary
I wired the
@librechat/agentsSDK's newtoolOutputReferencesfeature into the agent runtime, allowing the bash tool to reference prior tool outputs via{{tool<idx>turn<turn>}}placeholders in subsequent commands. The feature piggybacks on the existingexecute_codegate and requires no new env var or YAML capability.@librechat/agentsto^3.1.71-dev.0to pull inbuildBashExecutionToolDescriptionandRunConfig.toolOutputReferencessupport from agents#114 and agents#117.BASH_TOOL_DEFconstant intools.tswith a per-callbuildBashToolDef()factory that delegates to the SDK'sbuildBashExecutionToolDescription, conditionally appending the LLM-facing{{tool<idx>turn<turn>}}reference syntax guide whenenableToolOutputReferencesis true.enableToolOutputReferences: effectiveCodeEnvAvailableintoregisterCodeExecutionToolsfrominitializeAgent, tying the feature activation to the per-agent narrowed code-env flag (adminexecute_codecapability AND agent's owntoolslistingexecute_code).codeEnvAvailable?: booleanto theRunAgenttype inrun.ts, derive a run-level flag viaagents.some(a => a.codeEnvAvailable === true), and conditionally spreadtoolOutputReferences: { enabled: true }intoRun.createso the SDK registry activates for any run where the bash tool is registered.@librechat/agentsjest mocks ininitialize.test.tsandskills.test.tswith abuildBashExecutionToolDescriptionstub so existing test suites stay green when the on-disk SDK version lags the published export.tools.spec.tsassertingbash_tool.descriptioncontains the reference syntax guide iffenableToolOutputReferencesis true, and defaults to omitting it.run-summarization.test.tsassertingRun.createreceivestoolOutputReferences: { enabled: true }iff at least oneRunAgenthascodeEnvAvailable === true, covering present, absent, unset, and multi-agent OR scenarios.Change Type
Testing
Ran the full
packages/apitest suite (npx jest) with all tests passing. Verified the feature end-to-end by enabling an agent withexecute_codeand running a multi-step bash session where the second command contains a{{tool0turn0}}placeholder, confirming the prior output is substituted cleanly and a[ref: tool1turn0]annotation appears on the follow-up result. SDK defaults (~400 KB per output, 5 MB total) keep substituted payloads inside typical shellARG_MAXlimits.Test Configuration:
npx jestnpx tsc --noEmit@librechat/agents@3.1.71-dev.1Checklist