Skip to content

feat(agents): add Toolset support to ToolContext and AgentActivity#1525

Open
toubatbrian wants to merge 5 commits into
brian/refactor-tool-context-listfrom
brian/toolset
Open

feat(agents): add Toolset support to ToolContext and AgentActivity#1525
toubatbrian wants to merge 5 commits into
brian/refactor-tool-context-listfrom
brian/toolset

Conversation

@toubatbrian
Copy link
Copy Markdown
Contributor

@toubatbrian toubatbrian commented May 17, 2026

Summary

Adds Python-parity Toolset support: a stateful container that bundles a group of tools behind shared setup() / aclose() lifecycle hooks. Toolset instances can be passed directly into Agent({ tools: [...] }) alongside individual function tools; their tools are flattened into the agent's ToolContext and the runtime drives setup on activity start, close on activity teardown, and a diff on updateTools().

Closes the placeholder TODOs left in tool_context.ts from the previous list-syntax refactor.

Changes

Core (agents/src/llm/tool_context.ts)

  • New Toolset class with id, tools, setup(), aclose() (default no-ops, override in subclass).
  • New ToolCalledEvent / ToolCompletedEvent payload types (exported for plugin authors).
  • ToolContextEntry widened to FunctionTool | ProviderDefinedTool | Toolset.
  • updateTools() recurses into Toolsets and flattens their tools into _functionToolsMap / _providerTools while tracking the Toolset itself in _toolsets.
  • equals() compares _toolsets as an identity set (matches Python's {id(ts) for ts in self._tool_sets} semantics — order-insensitive).
  • Duplicate function-tool names continue to throw duplicate function name: <name>, including when the duplicate is contributed by a Toolset (Python parity).

Activity (agents/src/voice/agent_activity.ts)

  • New setupToolsets() / closeToolsets() driven by _startSession and _closeSessionResources.
  • setup() failures propagate to the caller after rolling back any toolsets that already initialized — the agent fails explicitly rather than running with half-set-up resources.
  • updateTools() now diffs added/removed Toolsets and runs lifecycle in setup → swap toolCtx → close order so a setup failure leaves the activity pointing at the previous (still-valid) ToolContext.
  • The IGNORE_ON_ENTER filter recurses through Toolsets so nested function tools also honor the flag.

Plugin migrations to ToolContext.flatten() + isFunctionTool filter
Toolset-contributed tools are included in _functionToolsMap, but several plugins were also rebuilding tool lists from Object.entries(toolCtx.functionTools), which would silently drop the Toolset references and confuse subsequent updateTools() diffs. Migrated:

  • plugins/google/src/utils.ts
  • plugins/mistralai/src/llm.ts
  • plugins/openai/src/realtime/realtime_model.ts — also fixes a real bug in _handleSessionUpdated() where the post-update retainedTools rebuild dropped Toolsets, causing them to be diffed-as-removed and prematurely aclose()d.
  • plugins/openai/src/responses/llm.ts
  • plugins/openai/src/ws/llm.ts
  • plugins/phonic/src/realtime/realtime_model.ts

plugins/openai/src/llm.ts (chat) and plugins/baseten/src/llm.ts left unchanged: they iterate Object.keys(toolCtx.functionTools) which already picks up flattened Toolset tools, mirroring Python's chat plugin.

Tests

  • agents/src/llm/tool_context.test.ts: new Toolset describe block (id/tools accessors, default no-op lifecycle, subclass override, flatten-into-ToolContext, duplicate-throw parity, identity-set equals() parity).
  • plugins/test/src/llm.ts: new toolset describe block runs against every LLM plugin's shared test suite — verifies the model can call a function tool nested inside a Toolset and that direct tools continue to work alongside.
  • agent_activity.test.ts / agent_activity_handoff.test.ts: existing tests pass (verified the toolset wiring doesn't disturb the fake activity scaffolding).

Example

  • New examples/src/basic_toolsets.ts showing a location_tools Toolset bundling getWeather + lookupTimezone and passed alongside an Agent.

Test plan

  • pnpm test --run agents/src/llm/tool_context.test.ts — 46/46 pass (40 prior + 6 new)
  • pnpm test --run agents/src/voice/agent_activity.test.ts agents/src/voice/agent_activity_handoff.test.ts — 24/24 pass
  • pnpm test --run plugins/openai/src/llm.test.ts plugins/google/src/llm.test.ts plugins/mistralai/src/llm.test.ts — 29/30 pass (1 pre-existing skip), including 2 new toolset cases per plugin
  • pnpm build — all 32 packages green
  • pnpm lint — clean (only pre-existing any warnings in unrelated files)
  • Manual: verify toolset aclose() runs on session close and that setup() rejection rolls back already-set-up toolsets

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 17, 2026

🦋 Changeset detected

Latest commit: 3c266ed

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 31 packages
Name Type
@livekit/agents Major
@livekit/agents-plugin-anam Major
@livekit/agents-plugin-assemblyai Major
@livekit/agents-plugin-baseten Major
@livekit/agents-plugin-bey Major
@livekit/agents-plugin-cartesia Major
@livekit/agents-plugin-cerebras Major
@livekit/agents-plugin-deepgram Major
@livekit/agents-plugin-elevenlabs Major
@livekit/agents-plugin-fishaudio Major
@livekit/agents-plugin-google Major
@livekit/agents-plugin-hedra Major
@livekit/agents-plugin-hume Major
@livekit/agents-plugin-inworld Major
@livekit/agents-plugin-lemonslice Major
@livekit/agents-plugin-liveavatar Major
@livekit/agents-plugin-livekit Major
@livekit/agents-plugin-minimax Major
@livekit/agents-plugin-mistral Major
@livekit/agents-plugin-mistralai Major
@livekit/agents-plugin-neuphonic Major
@livekit/agents-plugin-openai Major
@livekit/agents-plugin-phonic Major
@livekit/agents-plugin-resemble Major
@livekit/agents-plugin-rime Major
@livekit/agents-plugin-runway Major
@livekit/agents-plugin-sarvam Major
@livekit/agents-plugin-silero Major
@livekit/agents-plugins-test Major
@livekit/agents-plugin-trugen Major
@livekit/agents-plugin-xai Major

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@toubatbrian toubatbrian requested a review from a team May 17, 2026 22:55
Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

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

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 5 additional findings.

Open in Devin Review

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