Skip to content

feat: add max_tool_concurrency to core Agent and restore compatibility aliases - #366

Merged
frostming merged 2 commits into
devfrom
feat/tool-concurrency-compat-aliases
Oct 16, 2026
Merged

frostming merged 2 commits into
devfrom
feat/tool-concurrency-compat-aliases

Conversation

@frostming

Copy link
Copy Markdown
Collaborator

What changed and why

Two focused commits:

1. fix: restore compatibility aliases

0.6.0a2 removed modules and names that plugins written against 0.5.x / 0.6.0a1 still import. This restores them as aliases:

  • Modules, aliased with sys.modules like 0.6.0a1 did, so bub.tape is bub.core.tape:
    • bub.tape, bub.tools, bub.store, bub.sidecars → bub.core.*
    • bub.builtin.commands, bub.builtin.context → bub.core.commands, bub.core.context
  • bub.hooks.interception.LlmCallRequest / LlmCallResult / LlmCallDecision → LLMCall*. This is where plugins import them from; bub.core gets no aliases.

The four top-level aliases need only the kernel's dependencies.

2. feat: max_tool_concurrency on bub.core.Agent

agent = Agent(model=model, tools=[...], max_tool_concurrency=2)
  • Limits how many tool calls from one model response run at once. None (the default) keeps today's behavior: all calls run concurrently. 1 runs them one at a time, in order. Values below 1 raise ValueError.
  • ToolExecutor gets a max_concurrency argument and keeps the limiter on the instance: an asyncio.Semaphore, or nullcontext() when unlimited. The agent creates one executor per step, so the limit applies within one model response.

Impacted modules

bub.core.agent, bub.core.tools, bub.hooks.interception, the new alias modules, tests/test_compat_aliases.py, tests/test_core_agent.py, SDK docs (en + zh-cn).

Verification

  • uv run ruff check src tests: clean
  • uv run mypy src: clean
  • uv run pytest -q: 660 passed, 1 skipped
  • New tests:
    • each alias module is the new module, and the top-level aliases load no app dependencies
    • the interception aliases
    • peak tool concurrency is 3 / 2 / 1 for None / 2 / 1, and calls still start in order
    • non-positive limits are rejected

🤖 Generated with Claude Code

frostming and others added 2 commits October 16, 2026 16:52
…oads

Bring back bub.tape, bub.tools, bub.store, bub.sidecars, bub.builtin.commands
and bub.builtin.context as aliases of their bub.core modules, and keep the
LlmCallRequest / LlmCallResult / LlmCallDecision names in bub.hooks.interception.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Limit how many tool calls from one model response run at once. ToolExecutor
holds the limiter: a Semaphore, or nullcontext when unlimited.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
bub ae6c877 Commit Preview URL

Branch Preview URL
Oct 16 2026, 08:53 AM

@frostming
frostming merged commit debe365 into dev Oct 16, 2026
7 checks passed
@frostming
frostming deleted the feat/tool-concurrency-compat-aliases branch October 16, 2026 08:59
frostming added a commit that referenced this pull request Oct 18, 2026
    agent = Agent(model=model, tools=[...], max_tool_concurrency=2)

Limit how many tool calls from one model response run at once. `None`
(the default) runs them all concurrently; `1` runs them one at a time, in
order; values below 1 raise ValueError. `ToolExecutor` takes
`max_concurrency` and holds the limiter: an `asyncio.Semaphore`, or
`nullcontext()` when unlimited.
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