Skip to content

fix(agent-core): re-register builtin tools when provider resolves late - #1688

Merged
sailist merged 1 commit into
MoonshotAI:mainfrom
sailist:fix-late-provider-builtin-tools
Jul 14, 2026
Merged

fix(agent-core): re-register builtin tools when provider resolves late#1688
sailist merged 1 commit into
MoonshotAI:mainfrom
sailist:fix-late-provider-builtin-tools

Conversation

@sailist

@sailist sailist commented Jul 14, 2026

Copy link
Copy Markdown
Collaborator

Related Issue

N/A — no linked issue; the problem is explained below.

Problem

When the model provider becomes resolvable only after the session/agent has started — e.g. OAuth login or managed free-tokens model registration completing asynchronously — the agent runs with zero builtin tools. The system prompt still advertises the standard tools (Read/Bash/Glob/...), so the model emits tool calls, but every call fails with Tool "X" not found. The agent cannot read files, run commands, or use any builtin tool until the session is restarted/resumed (which rebuilds the table in a fresh process).

What changed

Root cause. initializeBuiltinTools() populates the executable tool table, but it is gated on hasProvider at every call site (ToolManager constructor, config update, skills-loaded, kaos-set). A provider that becomes resolvable asynchronously trips none of those checkpoints, so the table stays empty for the whole process — while the system prompt (which is independent of the table) keeps advertising the tools.

Fix. loopTools — which is re-read before every step — now self-heals: when the builtin table is empty but a provider is resolvable, it runs initializeBuiltinTools() on the spot, so the table is populated on the first step after the provider resolves. Steady state short-circuits on the empty-table check, so hasProvider is not re-evaluated per read (no per-step cost); a failure is logged and retried on the next read.

Poll-on-read is deliberate: the async registration path mutates the config the provider resolver reads without emitting any agent-level config event, so an event-driven re-init hook would not fire.

Tests. Added a regression test that builds an agent whose provider is initially unresolvable (empty live config), enables tools (table stays empty), then registers the provider asynchronously and asserts loopTools self-heals and the tools become dispatchable. Verified it fails without the fix and passes with it; the surrounding tool/turn/loop/mcp suites (230 tests) and tsc --noEmit are green.

Checklist

  • I have read the CONTRIBUTING document.
  • I have linked a related issue, or explained the problem above.
  • I have added tests that prove my feature works.
  • Ran gen-changesets skill, or this PR needs no changeset.
  • Ran gen-docs skill, or this PR needs no doc update.

When the model provider becomes resolvable only after the agent starts
(async OAuth / managed free-tokens registration), the builtin tool table
stayed empty: initializeBuiltinTools was gated on hasProvider at fixed
checkpoints and none fired. loopTools now self-heals on read once a
provider resolves, so tool calls no longer fail with "Tool not found".
@pkg-pr-new

pkg-pr-new Bot commented Jul 14, 2026

Copy link
Copy Markdown
pnpm dlx https://pkg.pr.new/@moonshot-ai/kimi-code@b559cf9
npx https://pkg.pr.new/@moonshot-ai/kimi-code@b559cf9

commit: b559cf9

@sailist
sailist merged commit 94c0ef8 into MoonshotAI:main Jul 14, 2026
15 checks passed

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b559cf97ff

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +841 to +843
if (this.builtinTools.size === 0 && this.agent.config.hasProvider) {
try {
this.initializeBuiltinTools();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Ensure shell commands also trigger lazy tool init

In late-provider sessions where the user runs a ! shell command before any model step, this lazy path is never reached: runShellCommand() still reads this.builtinTools.get('Bash') directly and returns “Bash tool is not available.” With this fix, prompting the model first heals the table, but the documented shell-command entry point remains broken until a prompt happens; factor this into a shared ensure step or call it from runShellCommand before the direct lookup.

Useful? React with 👍 / 👎.

@github-actions github-actions Bot mentioned this pull request Jul 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant